コマンドラインからスクリプトに値を渡すと、設定ファイルを作らなくても柔軟に動作を変えられます。
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 |
すべて文字列として格納されるため、数値として使う場合は型変換が必要です。
小さな確認コード
以下のスクリプトで、受け取った引数のリストと長さを確認できます。
# 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()
関数の中で扱うと整理しやすいです。
# 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
# 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()
で変換します。
# 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:]
のスライスをループするとシンプルです。
# 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)
で不足をチェックすると安全です。
# 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つ受け取ることです。
ここではテキストファイルの行数を数えます。
# 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)を計算します。
変換エラーや範囲チェックも入れておくと安心です。
# 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
フラグの有無でログ出力を切り替えます。
# 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)
チェックを先に行いましょう。
# 悪い例: 直接アクセスしてしまう
# 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つの引数として囲む必要があります。
# 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()
がどこかで結果が変わります。
# 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)
で中身を直接確認します。
デバッグ出力は問題切り分けに有効です。
# 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
への移行を検討しつつ、まずは本記事のパターンで確実に動かせる力を身につけてください。