Python argparse: 10분 안에 CLI 도구 만들기

발행: (2026년 5월 10일 AM 08:20 GMT+9)
10 분 소요
원문: Dev.to

Source: Dev.to

🎁 무료: AI 출판 체크리스트 — 파이썬으로 7단계
전체 파이프라인: (원하는 금액을 지불하세요, 최소 $9.99)

문제

간단한 스크립트를 작성하고 파일 이름을 하드코딩했지만, 곧바로 바꿔야 할 상황이 생깁니다.
sys.argv를 사용합니다:

import sys

filename = sys.argv[1]
count = int(sys.argv[2])

작동은 하지만, 문제가 생깁니다:

  • 인자를 주지 않고 실행 → IndexError.
  • 정수를 기대하는 곳에 정수가 아닌 값을 전달 → 크래시.
  • 도움말 텍스트도 없고, 검증도 없으며, 기본값도 없습니다.

스크립트를 사용하는 다른 사람은 어떻게 실행해야 하는지 알기 위해 소스 코드를 읽어야 합니다.

argparse인가?

argparse (표준 라이브러리)는 이 모든 문제를 해결합니다.
parse_args() 한 번 호출로 다음을 처리합니다:

  • sys.argv 읽기
  • 입력 검증
  • 도움말 출력 (--help)

기본 보일러플레이트

import argparse

parser = argparse.ArgumentParser(
    description="My CLI tool — does useful things."
)
args = parser.parse_args()

위치 인수

필수이며 이름이 아니라 위치로 식별됩니다:

parser.add_argument("filename", help="Path to the input file")
parser.add_argument("count", help="Number of items to process")

선택적 (플래그) 인자

-- 접두사를 사용합니다; 짧은 별칭은 선택 사항입니다:

parser.add_argument(
    "--output", "-o",
    help="Output file path",
    default="output.txt"
)
parser.add_argument(
    "--verbose", "-v",
    help="Enable verbose logging",
    action="store_true"
)

타입 변환 및 선택

argparse가 변환 및 검증을 수행하도록 합니다:

parser.add_argument(
    "--count", type=int, default=10,
    help="Number of items"
)
parser.add_argument(
    "--rate", type=float, default=1.5,
    help="Processing rate"
)
parser.add_argument(
    "--format",
    choices=["json", "csv", "txt"],
    default="json",
    help="Output format"
)

사용자가 --count hello를 실행하면, argparse는 깔끔한 오류 메시지를 출력하고 종료합니다—스택 트레이스는 표시되지 않습니다.

nargs와 리스트

예시의미
parser.add_argument("--title", required=True, help="Article title (required)")필수 옵션 인자
parser.add_argument("--tags", nargs="+", help="One or more tags")하나 이상 값 (+)
parser.add_argument("--tags", nargs="*", help="Zero or more tags")0개 이상 값 (*)

결과는 직접 반복(iterate)할 수 있는 파이썬 리스트입니다:

args = parser.parse_args()
for tag in args.tags:
    print(tag)

Boolean Flags (store_true / store_false)

parser.add_argument(
    "--dry-run",
    action="store_true",
    help="Simulate without writing"
)
parser.add_argument(
    "--no-color",
    action="store_false",
    dest="color",
    help="Disable color output"
)

사용법

python publish.py --dry-run   # args.dry_run is True
python publish.py             # args.dry_run is False
python publish.py --no-color # args.color is False

Sub‑commands (like git, docker, pip)

parser = argparse.ArgumentParser(description="Publish queue manager")
subparsers = parser.add_subparsers(dest="command", required=True)

# `publish` subcommand
publish_parser = subparsers.add_parser(
    "publish",
    help="Publish the next article in queue"
)
publish_parser.add_argument(
    "--dry-run",
    action="store_true",
    help="Simulate without publishing"
)

# `list` subcommand
list_parser = subparsers.add_parser(
    "list",
    help="Show the publish queue"
)
list_parser.add_argument(
    "--format",
    choices=["table", "json"],
    default="table"
)

args.command 은 어떤 서브커맨드가 선택되었는지를 알려 주며, 각 서브커맨드마다 고유한 인수가 있습니다.

--verbose / -v 패턴

런타임에 로깅 레벨을 설정하기 위해 --verbose를 사용하는 일반적인 패턴입니다:

import argparse
import logging

parser = argparse.ArgumentParser()
parser.add_argument(
    "--verbose", "-v",
    action="store_true",
    help="Enable debug logging"
)
args = parser.parse_args()

logging.basicConfig(
    level=logging.DEBUG if args.verbose else logging.INFO,
    format="%(levelname)s: %(message)s"
)

log = logging.getLogger(__name__)
log.info("Starting...")
log.debug("This only shows with --verbose")

전체 예제: 기사 게시 대기열 CLI

#!/usr/bin/env python3
"""
publish_queue.py — CLI for managing the article publish queue.
Usage: python publish_queue.py  [options]
"""

import argparse
import json
import logging
import sys
from pathlib import Path

QUEUE_FILE = Path("queue.json")

def load_queue() -> list[dict]:
    """Load the queue from JSON; return empty list if file missing."""
    if not QUEUE_FILE.exists():
        return []
    return json.loads(QUEUE_FILE.read_text())

def save_queue(queue: list[dict]) -> None:
    """Write the queue back to disk."""
    QUEUE_FILE.write_text(json.dumps(queue, indent=2))

def cmd_list(args: argparse.Namespace) -> None:
    queue = load_queue()
    if not queue:
        print("Queue is empty.")
        return
    for i, article in enumerate(queue, 1):
        status = "[published]" if article.get("published") else "[pending]  "
        tags = ", ".join(article.get("tags", []))
        print(f"{i}. {status} {article['title']} ({tags})")

def cmd_add(args: argparse.Namespace) -> None:
    queue = load_queue()
    article = {
        "title": args.title,
        "tags": args.tags or [],
        "published": False,
    }
    queue.append(article)
    save_queue(queue)
    logging.info("Added: %s", args.title)
    print(f"Added '{args.title}' to queue. Total: {len(queue)} articles.")

def cmd_publish(args: argparse.Namespace) -> None:
    queue = load_queue()
    pending = [a for a in queue if not a.get("published")]
    if not pending:
        print("No pending articles.")
        return
    next_article = pending[0]
    if args.dry_run:
        print(f"[DRY RUN] Would publish: {next_article['title']}")
        return
    next_article["published"] = True
    save_queue(queue)
    print(f"Published: {next_article['title']}")
    logging.info("Published: %s", next_article["title"])

def main() -> None:
    parser = argparse.ArgumentParser(
        description="Publish queue manager"
    )
    subparsers = parser.add_subparsers(dest="command", required=True)

    # add subcommand
    add_parser = subparsers.add_parser(
        "add",
        help="Add a new article to the queue"
    )
    add_parser.add_argument(
        "--title",
        required=True,
        help="Article title (required)"
    )
    add_parser.add_argument(
        "--tags",
        nargs="*",
        help="Zero or more tags"
    )
    add_parser.set_defaults(func=cmd_add)

    # list subcommand
    list_parser = subparsers.add_parser(
        "list",
        help="Show the publish queue"
    )
    list_parser.set_defaults(func=cmd_list)

    # publish subcommand
    publish_parser = subparsers.add_parser(
        "publish",
        help="Publish the next pending article"
    )
    publish_parser.add_argument(
        "--dry-run",
        action="store_true",
        help="Simulate without publishing"
    )
    publish_parser.set_defaults(func=cmd_publish)

    # global verbose flag
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="Enable debug logging"
    )

    args = parser.parse_args()

    # configure logging *after* parsing arguments
    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        format="%(levelname)s: %(message)s"
    )

    # dispatch to the chosen subcommand
    args.func(args)

if __name__ == "__main__":
    main()

스크립트를 다음과 같이 실행합니다:

python publish_queue.py add --title "My First Article" --tags python tutorial
python publish_queue.py list
python publish_queue.py publish --dry-run
python publish_queue.py publish -v

TL;DR

  • **argparse**는 한 줄 스크립트를 정교한 CLI로 변환합니다.
  • positionaloptional 인자를 정의하고, type conversion, choices, 그리고 리스트를 위한 nargs를 사용합니다.
  • 플래그에는 store_true / store_false 를 사용합니다.
  • git 스타일 서브 커맨드를 위해 sub‑parsers 를 활용합니다.
  • 로깅을 토글하기 위해 --verbose 플래그를 추가합니다.

한번 시도해 보세요—스크립트가 몇 분 안에 더 견고하고, 자체 문서화되며, 사용자 친화적으로 변합니다!

publish_queue.py – Argument‑Parser 기반 CLI

import argparse
import logging

# Example logging call used by the script
logging.info("Published: %s", next_article["title"])

def build_parser() -> argparse.ArgumentParser:
    """Create the top‑level argument parser."""
    parser = argparse.ArgumentParser(
        prog="publish_queue",
        description="Manage your article publish queue.",
    )
    parser.add_argument(
        "--verbose", "-v",
        action="store_true",
        help="Enable debug logging",
    )

    subparsers = parser.add_subparsers(dest="command", required=True)

    # ── list ────────────────────────────────────────────────────────
    list_parser = subparsers.add_parser("list", help="Show the publish queue")
    list_parser.set_defaults(func=cmd_list)

    # ── add ────────────────────────────────────────────────────────
    add_parser = subparsers.add_parser("add", help="Add an article to the queue")
    add_parser.add_argument("--title", required=True, help="Article title")
    add_parser.add_argument("--tags", nargs="*", help="Tags for the article")
    add_parser.set_defaults(func=cmd_add)

    # ── publish ─────────────────────────────────────────────────────
    publish_parser = subparsers.add_parser(
        "publish", help="Publish the next pending article"
    )
    publish_parser.add_argument(
        "--dry-run", action="store_true", help="Simulate without writing"
    )
    publish_parser.set_defaults(func=cmd_publish)

    return parser

def main() -> None:
    """Entry point for the CLI."""
    parser = build_parser()
    args = parser.parse_args()

    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.INFO,
        format="%(levelname)s: %(message)s",
    )

    # Dispatch to the appropriate sub‑command function
    args.func(args)

if __name__ == "__main__":
    main()

--help 출력

$ python publish_queue.py --help
usage: publish_queue [-h] [--verbose] {list,add,publish} ...

Manage your article publish queue.

positional arguments:
  {list,add,publish}
    list              Show the publish queue
    add               Add an article to the queue
    publish           Publish the next pending article

options:
  -h, --help          show this help message and exit
  --verbose, -v       Enable debug logging
$ python publish_queue.py add --help
usage: publish_queue add [-h] --title TITLE [--tags [TAGS ...]]

options:
  -h, --help           show this help message and exit
  --title TITLE        Article title
  --tags [TAGS ...]    Tags for the article

예시 워크플로우

# Add articles to the queue
python publish_queue.py add --title "Python argparse guide" \
    --tags python beginners tutorial
python publish_queue.py add --title "Automate your workflow" \
    --tags python automation

# List the queue
python publish_queue.py list
# 1. [pending]   Python argparse guide (python, beginners, tutorial)
# 2. [pending]   Automate your workflow (python, automation)

# Publish the next article (dry‑run first)
python publish_queue.py publish --dry-run
# [DRY RUN] Would publish: Python argparse guide

python publish_queue.py publish
# Published: Python argparse guide

# Check the updated queue with debug logging
python publish_queue.py list --verbose

Argparse 패턴 요약

패턴사용 시점
type=int / type=float모든 숫자 입력
choices=[...]고정된 유효 값 집합
required=True필수 옵션 인자
nargs="+" / nargs="*"값들의 리스트
action="store_true"불리언 플래그
add_subparsers()다중 명령 도구
set_defaults(func=…)서브 커맨드 함수에 디스패치

argparse가 자동으로 제공하는 것

  • -h/--helphelp= 문자열에서 자동 생성
  • Type validation – 명확한 오류 메시지, 트레이스백 없음
  • Default values – 도움말 출력에 문서화
  • Usage line – 인자 정의에서 자동 생성

제3자 라이브러리가 필요 없습니다. 모든 것이 파이썬 표준 라이브러리로 동작합니다.

추가 읽기 및 자료

  • 전체 파이프라인에서 publish‑queue CLIgermy5.gumroad.com/l/xhxkzz (원하는 금액을 지불, 최소 $9.99)
  • 자신을 검증하고 실행하는 첫 번째 자동화 파이썬 스크립트
  • Python 로깅: 자동화 스크립트에서 print() 사용 중단
  • Cron으로 파이썬 스크립트 예약하기: 초보자를 위한 완전 가이드
0 조회
Back to Blog

관련 글

더 보기 »