Pythonファイルをコマンドラインで実行したときの引数の受け取り方。(sys.argvを使う場合)

久々にコマンドラインツールを作った時に、引数の扱い方をド忘れしてしまっていたのでそのメモです。

ちなみに、argpaseっていう大変便利なライブラリもあるのでそれの使い方も紹介したいのですが、それは別記事に回して今回はもっとシンプルな方について書きます。

記事タイトルにも書いていますが、基本的には、sys.argvというのを使います。これは関数ではなく配列型のデータで、argv[0]にそのスクリプトのファイル名、argv[1]以降に、コマンドライン引数が入ります。

参考: sys — システムパラメータと関数 — Python 3.12.1 ドキュメント

また、Pythonのバージョン3.10 以降では、sys.orig_argv ってのも追加されています。

動かしてみるのが一番確認しやすいので、やってみましょう。
次のようなファイルを作ります。ファイル名は sample.py としました。

import sys


for i in range(len(sys.argv)):
    print(f"sys.argv[{i}]=", sys.argv[i])

for i in range(len(sys.orig_argv)):
    print(f"sys.orig_argv[{i}]=", sys.orig_argv[i])

ではこれを実行してみましょう。一旦実行権限とかつけてないので、明示的にpythonコマンドとして実行します。

引数はただ表示するだけで何も処理に影響はないので、デタラメにつけてみました。

% python sample.py file.txt -l aaa.txt "bbb" --name=xyz
sys.argv[0]= sample.py
sys.argv[1]= file.txt
sys.argv[2]= -l
sys.argv[3]= aaa.txt
sys.argv[4]= bbb
sys.argv[5]= --name=xyz
sys.orig_argv[0]= /Users/{macのユーザー名}/.pyenv/versions/3.11.1/bin/python
sys.orig_argv[1]= sample.py
sys.orig_argv[2]= file.txt
sys.orig_argv[3]= -l
sys.orig_argv[4]= aaa.txt
sys.orig_argv[5]= bbb
sys.orig_argv[6]= --name=xyz

はい、argvの方は、[0]番目にスクリプト名が表示され、[1]以降に引数が格納されていましたね。”bbb”のところに注目ですが、ダブルクオーテーションは外されています。

orig_argv は、ファイル名の前の、pythonパスまで入っています。the original command line arguments というから、コマンドに打った python がそのまま入ってるかと思ったらフルパスに展開されています。

ちなみに、sys.argv[0]= sample.py と sys.orig_argv[1]= sample.py のスクリプトパスですが、これはコマンドラインで打ったファイルパスがそのまま表示されいます。どういうことかというと、現在はカレントディレクトリで実行したからこのように表示されているだけで、違う場所から相対パスや絶対パスで指定して実行したらこの中身は変わります。フルパスで指定したらフルパスが入ります。

続いて、このファイルに実行権限をつけて頭のpythonを外してみましょう。
ファイルの先頭に、 #!/usr/bin/env python のシバンを挿入して、chmod で実行権限つけときます。

これで実行すると次のようになります。(引数少し減らしました)

% ./sample.py file.txt -l aaa.txt
sys.argv[0]= ./sample.py
sys.argv[1]= file.txt
sys.argv[2]= -l
sys.argv[3]= aaa.txt
sys.orig_argv[0]= /Users/{macのユーザー名}/.pyenv/versions/3.11.1/bin/python
sys.orig_argv[1]= ./sample.py
sys.orig_argv[2]= file.txt
sys.orig_argv[3]= -l
sys.orig_argv[4]= aaa.txt

sys.argv の方はさっきと大して変わらないですね。カレントディレクトリにパスが通ってないので、スクリプトの指定が./ファイル名 になったのが反映されています。

orig_argv の方も先の結果とほぼ変わりませんが、これはちょっと意外でした。the original command line arguments というから、コマンドラインで python 省略したらここからも省略されると思ってたら相変わらずpython本体のパスが登場しています。

orig_argv が何を意図して追加されたのかがよくわからないのですが、とりあえず argv の方を使っておけば良さそうです。

[1]以降の引数たちは冒頭でも書いたargpaseってライブラリで取ることが多く、sys.argvで取得するのはよほど単純なスクリプトの場合に限られるかなとも思います。となると、もしかしたらargv[0]のファイル名の方がよく使うかもしれないですね。

おまけ

記事の本題と逸れるのですが、argv[0]でスクリプト名が取れるとしたら、スクリプトのフルパスやカレントディレクトリの取得方法が気になるかもしれないのでその撮り方もメモしておきます。

結論を言うと、ファイル名は __file__ って特別な変数に格納されています。
また、カレントディレクトリは os.getcwd() で取れます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です