Open Source 개발

[오픈소스 개발기] pypipo : CLI 만들기

콜레오네 2023. 7. 8. 18:25

내가 만든 프로젝트를 오픈소스로 공개하기로 했다.

 

https://github.com/AutoPipo/pypipo

 

GitHub - AutoPipo/pypipo: Python Library based on EasyPipo

Python Library based on EasyPipo. Contribute to AutoPipo/pypipo development by creating an account on GitHub.

github.com

 

오픈소스 공개 과정에서 고민의 흔적을 남겨보려 한다.

 


파이썬 라이브러리를 사용할 때

인터프린터 환경에서 돌아갈 수 있게 하기 위해 cli 기능을 만들어보기로 했다.

 

from pypipo.libs.process import Painting, LineDrawing, ColorspaceIndexing
from pypipo.libs.utils import *

def pipo_convert(filepath,
                 outputpath, 
                 color_label = True,
                 **kwargs):
    painting = Painting(filepath)
    painting_img, color_index_map = painting.run(**kwargs)
    color_indexs, color_rbg_values = painting.get_clustered_color_info(painting_img)

    
    drawing = LineDrawing(color_index_map)
    line_drawn_image = drawing.run(outline = True)
    # TODO: change values name : img_lab, lab
    img_lab, lab = drawing.get_image_lab(color_rbg_values, painting_img)

    numbering = ColorspaceIndexing(painting_img, line_drawn_image, color_indexs, color_rbg_values)
    output = numbering.run(img_lab, lab, color_label = color_label)
    img_save(outputpath, output)
    
    return

 

우선, 내가 만든 각종 기능들을 import 해와야 한다, 당연히.

그리고 주요 기능이 다 들어가있는, main이 되는 하나의 함수를 작성해준다.

 

고민 끝에, pipo_convert라고 함수 네이밍을 하였다.

파라미터는 꼭 필요한 input, output file path만 집어넣었고, output 결과물에 영향을 줄 수 있는

color_label 파라미터 하나만 추가로 지정해주었고, default는 true로 세팅했다.

나머지 파라미터는 모두 kwargs에 넣어서 쓰고싶은 것만 쓰도록 해주었다.

 

저 함수만 실행시키면, 완벽하게 기능이 돌아가는 구조이다.

 

그럼, 이제 저 함수를 활용해서 CLI를 만들어보자

 

import click
import __version__
from convert import pipo_convert


class Config(object):
    def __init__(self):
        self.config = {}

    def set_config(self, key, value):
        self.config[key] = value

 

우선 click 라이브러리를 가져왔다. cli를 만들어주는 핵심 라이브러리다.

내가 만든 pipo_convert도 당연히 불러와야한다.

 

Config 클래스를 작성해주었다.

이 라이브러리의 정보들을 담아줄 객체를 생성하기 위함이다.

 

pass_config = click.make_pass_decorator(Config)


@click.group(name="pypipo")
@click.version_option(version=__version__)
# @click.argument("filepath", type=click.Path(exists=True))
@click.pass_context
def cli(ctx, *args, **kwargs):
    """Pypipo : Automatically convert to PIPO Painting canvas."""
    ctx.obj = Config()
    for key, value in kwargs.items():
        ctx.obj.set_config(key, value)
  • group : 그룹을 지정한다. 여기에 여러 command를 만들 수 있다. 단일 기능만 사용할 예정이라면, group이 아니라
  • command 하나만 사용해도 되지만, 또 추가하고 싶은 기능이 생길지 누가 아는가?
  • pass_context : click이 실행될 때 지정된 매게면수를 kwargs로 전달받게 된다. 콜백에서 pass-context를 통해 문객 객체를 전달할 수 있다. 아무튼 click 함수에서 콜백 시, 매개변수 전달을 위해 필요하다고 하니, 사용해주도록 하자

 

@cli.command("convert")
@click.option(
    "-n",
    "--number",
    default=16,
    help="Number of color clustered",
)
@click.option(
    "-a",
    "--attempts",
    default=1,
    help="How many iterate try to k-means clustering",
)
... 중간 생략
@click.option(
    "-c",
    "--color_label",
    default=True,
    help="Show color label at left-top of output image",
)
@click.argument("filepath", type=click.Path(exists=True))
@click.argument("output_path", type=click.Path(writable=True))
@pass_config
def convert(c, *args, **kwargs):
    filepath = kwargs.pop("filepath")
    output_path = kwargs.pop("output_path")
    color_label = kwargs.pop("color_label")
    output = pipo_convert(filepath, output_path, color_label, **kwargs)

    click.echo("Image Converting Finished!")

    return output
  • command : 아까 pypipo라는 group을 만들었으니, command를 추가해주자. pypipo가 명령할 수 있는 것들중 하나라는 의미다.
  • option : 이녀석들이 파라미터가 된다. 한자릿수의 짧은 변수, 그리고 롱네임의 변수를 선언해주어 사용할 수 있도록 하고, default 값과 help를 작성해준다. 
  • argument : 이녀석들은 필수 값이다. option이 선택이라면, argument는 꼭 넣어야 실행되는 필수 파라미터인 셈이다. 여기서 나는 filepath를 입력하도록 했는데, exists = True로 세팅하면 os 내에서 파일이 실제로 존재하는지 확인하고, 그렇지 않으면 fail이 뜬다. writable=True는 파일을 쓸 수 있는지에 대한 여부.

 

결국 convert 함수에서 최종 실행해준다. 파라미터 에러 체크를 할 필요가 있다면 여기서 해줄 수 있다.

import 해온 pipo_convert를 실행시켜준다.

프로세스가 끝난다면, echo 함수를 통해 끝났다고 알려주는 정도로 작성을 마쳤다.

 

D:\>python .
Usage: python -m  [OPTIONS] COMMAND [ARGS]...

  Pypipo : Automatically convert to PIPO Painting canvas.

Options:
  --version  Show the version and exit.
  --help     Show this message and exit.

Commands:
  convert



D:\>python . convert
Usage: python -m  convert [OPTIONS] FILEPATH OUTPUT_PATH
Try 'python -m  convert --help' for help.

Error: Missing argument 'FILEPATH'.



D:\>python . convert --help
Usage: python -m  convert [OPTIONS] FILEPATH OUTPUT_PATH

Options:
  -n, --number INTEGER       Number of color clustered
  -a, --attempts INTEGER     How many iterate try to k-means clustering
  -u, --is_upscale BOOLEAN   Expand size of image
  -t, --target_size INTEGER  Size that want to expand image.
  -d, --div INTEGER          Reducing numbers of color on image
  -S, --sigma INTEGER        bilateralFilter Parameter
  -c, --color_label BOOLEAN  Show color label at left-top of output image
  --help                     Show this message and exit.

이렇게 정보가 표현되는게 보인다.

-한자릿수 파라미터

-- 두자릿수 파라미터

로 option 세팅이 가능하다.

 

한 줄로 간편하게 실행이 가능해진 것 같다.

 

반응형