Python

[Typer] Python으로 CLI App 만들기

llHoYall 2024. 3. 30. 15:27

TyperFastAPI를 만든 곳에서 만든 CLI app을 만들수 있도록 도와주는 라이브러리입니다.

FastAPI도 사용성이 너무 좋았었는데, Typer도 역시 너무 맘에 들어서 이렇게 소개를 드립니다.

Installation

먼저 필요한 패키지를 설치합니다.

$ pip install "typer[all]"

Rich라는 패키지도 설치가 되는 데 이것도 아주 재밌는 패키지라서 app 만들 때 종종 사용하려고 합니다. ㅎㅎ

Create a First Example

간단히 사용 예제를 보여드릴게요.

import typer

def main(name: str):
    print(f"Hello {name}")

if __name__ == "__main__":
    typer.run(main)

argparse 같은 내장 패키지를 사용할 때보다 훨씬 간단하죠?

typer.run()으로 묶어준 것 뿐인데 벌써 CLI app이 완성되었어요.

실행을 시켜보면 요렇게 이미 기본 구조가 완성되어서 사용자에게 사용법도 알려줍니다.

시킨대로 --help 옵션을 주면 깔끔하게 도움말을 보여줍니다.

사용법에 맞게 실행을 하면 원하는대로 함수가 실행되요.

Upgrade the Example

앱을 확장하여 조금 더 복잡한 예제를 보여드리겠습니다.

import typer

app = typer.Typer()

@app.command()
def hello(name: str):
    print(f"Hello {name}")

@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        print(f"Goodbye Mr. {name}. Have a good day.")
    else:
        print(f"Bye {name}!")

if __name__ == "__main__":
    app()

이번에는 2개의 명령을 만들었습니다.

typer.Typer()를 사용하여 app을 생성하고, 이 app 객체를 사용한 것이 가장 큰 차이점입니다.

등록한 명령어 2개가 보이고, 기본 옵션에 보면 app을 바로 설치할 수 있게 만들어 주기도 하고, 자동 완성기능도 사용할 수 있네요.

각각의 명령어의 도움말을 출력해볼게요.

기본값을 가진 인자가 어떻게 보이는지도 확인할 수 있죠?

새로 만든 명령어도 사용해 보았습니다.

Special Feature

이 외에도 유용하게 사용할 수 있는 기능들을 많이 제공하고 있는데, 그 중에서도 개인적으로 CLI 앱을 만들 때 자주 사용하게 되는 프로그레스 바를 한 번 보여드릴게요.

import time

import typer
from rich.progress import track

def main():
    total = 0
    for value in track(range(100), description="Processing..."):
        time.sleep(0.01)
        total += 1
    print(f"Processed {total} things.")

if __name__ == "__main__":
    typer.run(main)

이제, 실행을 시켜볼까요?

 

마지막으로, loading을 나타내는 것을 보여드릴게요.

웹이나 외부 프로그램과의 통신이 필요한 경우에 종종 사용하는 건데, 그동안은 ... 등으로만 표현해왔는데 Typer에서는 이것도 예쁘게 보여줄 수 있습니다.

import time

import typer
from rich.progress import Progress, SpinnerColumn, TextColumn

def main():
    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        transient=True,
    ) as progress:
        progress.add_task(description="Processing...", total=None)
        progress.add_task(description="Preparing...", total=None)
        time.sleep(5)
    print("Done!")

if __name__ == "__main__":
    typer.run(main)

실행을 시키면 요렇게 보입니다.

Wrap Up

이번에는 Python에서 CLI app을 만들 때 유용한 Typer라는 패키지를 소개해 드렸습니다.

개인적으로 이걸 알게된 이후로 CLI는 무조건 이걸로만 만들 정도로 좋아하는 거라서 다른 분들께도 꼭 소개드리고 싶었어요. 😆