閉じる

Pythonのsys.argvでコマンドライン引数を取得する基本と使い方

コマンドラインからスクリプトに値を渡すと、設定ファイルを作らなくても柔軟に動作を変えられます。

Pythonではsys.argvを使うのが基本です。

本記事ではsys.argvの仕組みから実行例、実用的なサンプル、注意点までを初心者向けに丁寧に解説します

まずは構造を理解し、シンプルな活用から始めましょう。

Pythonのsys.argvとは?

コマンドライン引数の意味

コマンドライン引数は、スクリプト実行時にプログラムへ渡す追加の文字列データです。

例えば、ファイル名やモード(--debugなど)、計算に使う数値などを外部から指定できます。

同じコードでも引数次第で振る舞いを変えられるため、使い勝手が大幅に向上します。

具体例のイメージ

python resize.py input.jpg 800」のように実行すれば、画像ファイル名と幅(800)を引数として渡せます

GUIを作らなくても、1行のコマンドで目的の処理を指定できます。

sys.argvの構造(リストとargv[0])

sys.argv文字列のリストです。

argv[0]には通常、実行中スクリプトのパス(または名前)が入り、argv[1]以降がユーザーが渡した引数です。

下表は典型的な構造です。

インデックス含まれる値
0スクリプト名(パス)script.py
1第1引数input.txt
2第2引数10
3第3引数–debug

すべて文字列として格納されるため、数値として使う場合は型変換が必要です。

小さな確認コード

以下のスクリプトで、受け取った引数のリストと長さを確認できます。

Python
# file: show_argv.py
import sys  # sysモジュールをインポート

def main():
    # sys.argvは「リスト」。中身と個数を表示します。
    print("argv:", sys.argv)
    print("length:", len(sys.argv))
    # 先頭要素(argv[0])はスクリプト名(パス)であることが多い
    print("argv[0]:", sys.argv[0])

if __name__ == "__main__":
    main()
実行結果
$ python3 show_argv.py a b c
argv: ['show_argv.py', 'a', 'b', 'c']
length: 4
argv[0]: show_argv.py

importの仕方と使う場所

sys.argvを使うには、import sysをスクリプトの冒頭(通常は先頭付近)で記述します

関数内でsys.argvを参照しても構いませんが、エントリーポイントとなるmain()関数の中で扱うと整理しやすいです。

Python
# file: where_to_import.py
import sys  # 1. 先頭でインポート(推奨)

def parse_args():
    # 2. 関数内でsys.argvを使える
    return sys.argv[1:]  # スクリプト名を除いた引数部分

def main():
    args = parse_args()
    print("args:", args)

if __name__ == "__main__":
    # 3. エントリーポイントから処理開始
    main()

「先頭でimport」→「関数で処理」→「mainで実行」という流れにすると、構造が明確になります

sys.argvの使い方(実行と取得)

実行コマンド例(Windows/Mac/Linux)

環境によりPythonの起動コマンドが少し異なりますが、使い方の基本は「python(またはpython3) スクリプト名 引数…」です

代表的な呼び出し方

  • Windows(Command Prompt/PowerShell): python script.py arg1 arg2 または py -3 script.py arg1
  • macOS/Linux: python3 script.py arg1 arg2 または環境によりpython
Shell
# Windows (PowerShell/Command Prompt)
python show_argv.py apple 123 --debug

# macOS / Linux (bash/zsh)
python3 show_argv.py apple 123 --debug

同じスクリプトでも、与える引数を変えるだけで動作を切り替えられるのが利点です。

文字列として受け取る(型変換が必要)

sys.argv内はすべて文字列なので、数値として使うときはint()float()で変換します。

Python
# file: greet_and_age.py
import sys

def main():
    if len(sys.argv) < 3:
        print("使い方: python greet_and_age.py <name> <age>")
        return

    name = sys.argv[1]             # 文字列のまま使う
    age_str = sys.argv[2]          # 文字列として受け取る
    try:
        age = int(age_str)         # 必要に応じて数値に変換
    except ValueError:
        print(f"年齢は数値で指定してください: {age_str!r}")
        return

    print(f"こんにちは、{name}さん。あなたは{age}歳ですね。")

if __name__ == "__main__":
    main()
実行結果
$ python3 greet_and_age.py Sato 20
こんにちは、Satoさん。あなたは20歳ですね。

文字列→数値の変換は例外が起きやすいため、try/exceptでの保護が実務では有効です。

複数引数の取得(ループで処理)

引数が可変個の場合は、sys.argv[1:]のスライスをループするとシンプルです。

Python
# file: list_args.py
import sys

def main():
    args = sys.argv[1:]  # スクリプト名を除く全部
    if not args:
        print("引数がありません。")
        return

    # インデックスも使いたい場合はenumerateを利用
    for i, arg in enumerate(args, start=1):
        print(f"第{i}引数: {arg}")

if __name__ == "__main__":
    main()
実行結果
$ python3 list_args.py red green blue
第1引数: red
第2引数: green
第3引数: blue

sys.argv[1:]は「ユーザーが渡したすべての引数」を簡単に扱える基本テクニックです。

引数不足の判定(lenチェック)

インデックスで直接アクセスする前にlen(sys.argv)で不足をチェックすると安全です。

Python
# file: need_two_args.py
import sys

def main():
    if len(sys.argv) < 3:
        print("使い方: python need_two_args.py <src> <dst>")
        # 終了コードを明示すると親プロセスに失敗を伝えられる
        sys.exit(2)

    src = sys.argv[1]
    dst = sys.argv[2]
    print(f"コピー元: {src}, コピー先: {dst}")

if __name__ == "__main__":
    main()

実行結果の例(不足時):

実行結果
$ python3 need_two_args.py only_src
使い方: python need_two_args.py <src> <dst>

要件を満たさないときはメッセージと終了コードで明確に失敗を示すと親切です。

sys.argvの実用例

ファイル名を1つ受け取る

もっともよくある用途は、処理対象のファイルパスを1つ受け取ることです。

ここではテキストファイルの行数を数えます。

Python
# file: count_lines.py
import sys

def count_lines(path: str) -> int:
    # 可能ならwith構文で安全にファイルを開く
    with open(path, "r", encoding="utf-8") as f:
        return sum(1 for _ in f)

def main():
    if len(sys.argv) < 2:
        print("使い方: python count_lines.py <file>")
        sys.exit(2)

    path = sys.argv[1]
    try:
        n = count_lines(path)
    except FileNotFoundError:
        print(f"ファイルが見つかりません: {path!r}")
        sys.exit(1)
    except UnicodeDecodeError:
        print(f"文字コードの問題が発生しました。encodingの指定を見直してください: {path!r}")
        sys.exit(1)

    print(f"{path}: {n} 行")

if __name__ == "__main__":
    main()
実行結果
$ python3 count_lines.py sample.txt
sample.txt: 42 行

ファイル入出力とsys.argvの組み合わせは現場でも頻出です

実運用では例外処理を必ず入れましょう。

数値Nを受け取り計算する

引数で受け取った数値Nまでの総和(1+…+N)を計算します。

変換エラーや範囲チェックも入れておくと安心です。

Python
# file: sum_to_n.py
import sys

def sum_to_n(n: int) -> int:
    # 高速に求める公式: n(n+1)//2
    return n * (n + 1) // 2

def main():
    if len(sys.argv) < 2:
        print("使い方: python sum_to_n.py <N>")
        sys.exit(2)

    try:
        n = int(sys.argv[1])
    except ValueError:
        print("Nは整数で指定してください。")
        sys.exit(2)

    if n < 0:
        print("Nは0以上で指定してください。")
        sys.exit(2)

    total = sum_to_n(n)
    print(f"1から{n}までの総和: {total}")

if __name__ == "__main__":
    main()
実行結果
$ python3 sum_to_n.py 10
1から10までの総和: 55

数値引数はint()などの型変換と妥当性チェックをセットで扱うのが基本です。

簡単なフラグを判定する(–debug など)

フラグは存在すれば有効という単純な判定が向いています。

ここでは--debugフラグの有無でログ出力を切り替えます。

Python
# file: flags_demo.py
import sys
from datetime import datetime

def main():
    args = sys.argv[1:]

    # --debug が含まれているかを判定(位置はどこでもOK)
    debug = "--debug" in args

    # 位置引数(フラグ以外)だけを取り出す簡易処理
    positional = [a for a in args if not a.startswith("--")]
    if not positional:
        print("使い方: python flags_demo.py [--debug] <name>")
        sys.exit(2)

    name = positional[0]

    if debug:
        print(f"[DEBUG {datetime.now()}] argv={sys.argv!r}")

    print(f"Hello, {name}!")

if __name__ == "__main__":
    main()
実行結果
$ python3 flags_demo.py --debug Alice
[DEBUG 2024-01-01 12:34:56.789012] argv=['flags_demo.py', '--debug', 'Alice']
Hello, Alice!

フラグが増える場合はargparseの導入を検討しましょう(本記事ではsys.argvに絞って解説しています)。

sys.argvの注意点とコツ

IndexErrorを防ぐ(lenで安全に)

最も多い失敗は「引数が足りないのにargv[1]へアクセス」してIndexErrorになることです。

常にlen(sys.argv)チェックを先に行いましょう。

Python
# 悪い例: 直接アクセスしてしまう
# name = sys.argv[1]  # 引数がなければIndexError

# 良い例: 先にチェック
import sys
if len(sys.argv) < 2:
    print("使い方: python script.py <name>")
    sys.exit(2)
name = sys.argv[1]
print(f"name={name}")

例外が出ると初心者には原因が分かりづらいため、丁寧な使い方メッセージと終了コードを整えましょう。

スペースや日本語は引用符で囲む

コマンドラインはスペース区切りで引数を分解します。

スペースや日本語を含む値は引用符で1つの引数として囲む必要があります。

Shell
# Windows (PowerShell/Command Prompt) は通常ダブルクォート
python3 show_argv.py "My Document.txt" "こんにちは 世界"

# macOS / Linux (bash/zsh) はシングル or ダブルどちらも可
python3 show_argv.py 'My Document.txt' 'こんにちは 世界'

引用符を忘れると引数が分割され、意図しない複数引数になってしまいます

カレントディレクトリに依存する点

プログラムは実行時のカレントディレクトリ(作業ディレクトリ)に影響を受けます

相対パスを引数でもらった場合、os.getcwd()がどこかで結果が変わります。

Python
# file: show_paths.py
import sys, os

print("cwd:", os.getcwd())
print("argv[0]:", sys.argv[0])
if len(sys.argv) > 1:
    print("arg1 (as given):", sys.argv[1])
実行結果
$ cd /projects
$ python3 scripts/show_paths.py data/input.txt
cwd: /projects
argv[0]: scripts/show_paths.py
arg1 (as given): data/input.txt

相対パスを扱うときは現在位置に依存して解決される点を覚えておきましょう。

より堅牢にするにはpathlib.Pathで絶対パス化する方法があります(詳細は別記事で解説)。

printで中身を確認する

思った通りに引数が渡っているか不安なときは、print(sys.argv)で中身を直接確認します。

デバッグ出力は問題切り分けに有効です。

Python
# file: debug_argv.py
import sys
print("argv(repr):", repr(sys.argv))
実行結果
$ python3 debug_argv.py "A B" C
argv(repr): ['debug_argv.py', 'A B', 'C']

repr形式(リスト表記)で見えると、どこで区切られたかが一目で分かります。

まとめ

sys.argvは「スクリプト名を含む文字列リスト」で、argv[1:]がユーザー引数という基本を押さえれば、ファイル処理や数値計算、簡単なフラグ判定まで幅広く対応できます。

実装の要点は、lenチェックでIndexErrorを防ぐこと必要に応じて型変換と例外処理を行うことスペースや日本語は引用符で囲むこと、そして困ったらprint(sys.argv)で確認することです。

引数が複雑になってきたらargparseへの移行を検討しつつ、まずは本記事のパターンで確実に動かせる力を身につけてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!