連載
» 2021年12月21日 05時00分 公開

[解決!Python]Pythonスクリプトに与えられたコマンドライン引数を処理するには解決!Python

sysモジュールのargv属性を使って、スクリプトファイルに与えられたコマンドライン引数を受け取り、それを処理する方法を紹介する。

[かわさきしんじ,Deep Insider編集部]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「解決!Python」のインデックス

連載目次

sys.argvの基本

import sys

# sys.argv属性にはpythonコマンドで実行するスクリプトに
# 与えられたコマンドライン引数が渡される(スクリプトファイル名を含む)
print('sys.argv:', sys.argv)

script_file_name = sys.argv[0]
print('script file name:', script_file_name)

cmdline_option0 = sys.argv[1]
print('command line option[0]:', cmdline_option0)

# sys.orig_argv属性にはpythonコマンドに与えられたコマンドライン引数が
# スクリプトファイル名などを含み、全て渡される(Python 3.10以降)
print('sys.orig_argv:', sys.orig_argv)


コマンドライン引数の列挙

import sys

for idx, arg in enumerate(sys.argv):
    print(f'arg[{idx}]: {arg}')


コマンドライン引数を位置引数として扱う例

import sys

def calc(x, y, op='plus'):
    if op == 'plus':
        return x + y
    elif op == 'minus':
        return x - y
    elif op == 'multi':
        return x * y
    elif op == 'div':
        return x // y
    else:
        raise ValueError('op must be plus, minus multi or div')

if len(sys.argv) == 3# 2引数ならそれらを加算
    x = float(sys.argv[1])
    y = float(sys.argv[2])
    result = calc(x, y)
elif len(sys.argv) == 4# 3引数は「演算子, 値1, 値2」と見なす
    op = sys.argv[1]
    x = float(sys.argv[2])
    y = float(sys.argv[3])
    if op in ['plus', 'minus', 'multi', 'div']:
        result = calc(x, y, op)
    else:
        result = 'not supported operation'
else:
    result = 'not supported operation'

print(result)


コマンドライン引数(オプション)を解析する例

import sys

# コマンドライン引数をオプションの形(-X 値/-X)で指定する例
# 以下の辞書で値がTrueのオプションは、続けてその値を指定するもの
# 値がFalseのオプションは何らかのスイッチ(True/False値を持つ)
# 例:python3 kw_args.py -x hoge -y huga -z
options = {'-x': True, '-y': True, '-z': False}
args = {'x': 'foo', 'y': 'bar', 'z': False# デフォルト値

for key in options.keys():
    if key in sys.argv:
        idx = sys.argv.index(key)
        if options[key]:
            value = sys.argv[idx+1]
            if value.startswith('-'):
                raise ValueError(f'option {key} must have a value.')
            args[key[1:]] = value
            del sys.argv[idx:idx+2]
        else:
            args[key[1:]] = True
            del sys.argv[idx]

print("args['x']:", args['x'])
print("args['y']:", args['y'])
print("args['z']:", args['z'])

# 残ったsys.argvの要素は位置引数と考える(スクリプトファイル名を除く)
print(f'positional argument:', sys.argv[1:])


sys.argv属性

 Pythonのスクリプトを実行する際には、その実行に必要な情報を与えたり、振る舞いを変更したりするためにコマンドライン引数として何らかの値を渡せる。例えば、以下のような渡し方が考えられる。

$ python3 foo.py 1 2  ← foo.pyに1と2を渡す
$ python3 foo.py -x 1 -y 1 ← bar.pyの-xオプションと-yオプションに1を指定



 最初の例は、Pythonの関数でいうところの位置引数に相当すると考えられる。つまり、コマンドライン引数の順番でその値が意味するところが決まっている。2つ目の例はキーワード引数に相当すると考えられる。つまり、「-オプション名 その値」という形でオプション(キーワード引数名)とその値を指定するものだ。加えて、あるオプションを指定すると、その値がTrue(またはFalse)に、指定しなければその値がFalse(またはTrue)となるようなスイッチと呼ばれる形式の指定も考えられる。

 いずれにせよ、このようにしてスクリプトファイルに渡されたコマンドライン引数は、そのスクリプトファイル内で処理する必要がある。Pythonでコマンドライン引数を処理する際には、sysモジュールのargv属性を使うか、argparseモジュールを使用することが多い。本稿では、このうちsys.argv属性を使う方法を紹介する。

 sys.argv属性には、スクリプト開始時にコマンドライン引数として渡された値が文字列リストの形で保存される。このとき、先頭にはスクリプトファイル名が、その後にコマンドライン引数が格納される。

import sys

# sys.argv属性にはpythonコマンドで実行するスクリプトに
# 与えられたコマンドライン引数が渡される(スクリプトファイル名を含む)
print('sys.argv:', sys.argv)

script_file_name = sys.argv[0]
print('script file name:', script_file_name)

cmdline_option0 = sys.argv[1]
print('command line option[0]:', cmdline_option0)


 上のスクリプトファイル(foo.pyファイル)を以下のようなコマンドライン引数を指定して実行した例を以下に示す。

> python3 foo.py hogehoge hugahuga
sys.argv: ['foo.py', 'hogehoge', 'hugahuga']
script file name: foo.py       
command line option[0]: hogehoge



 sys.argv属性の先頭要素がスクリプトファイルの名前(foo.py)に、その次の要素がコマンドライン引数になっていることを確認してほしい。

 このようにsys.argv属性の要素に対してインデックスを使ってアクセスしようとするときには、そのインデックス位置に要素がなければ、例外が発生することには注意しよう。例えば、コマンドライン引数なしでfoo.pyファイルを実行すると次のように例外が発生する。これはsys.argv[1]が存在しないからだ。

> python3 foo.py
sys.argv: ['foo.py']
script file name: foo.py
Traceback (most recent call last):
  File "C:\pytips\pytips_69\test\foo.py", line 11, in <module>
    cmdline_option0 = sys.argv[1]
IndexError: list index out of range



 インデックスを使って、コマンドライン引数にアクセスするのは、特定の位置にあるコマンドライン引数が特定の意味を持つことを前提としてスクリプトを書く場合となるだろう(例は後述)。

 一方、sys.argv属性は単なる文字列リストなので、以下のようにして反復して処理してもよい。

import sys

for idx, arg in enumerate(sys.argv):
    print(f'arg[{idx}]: {arg}')


 このとき、スクリプトファイルの名前が不要であれば、sys.argv[1:]と書くことで渡されたコマンドライン引数だけを取り出すことも可能だ。コマンドライン引数に与えた値が位置に応じて特定の意味を持つのではなく、反復的に処理できる場合にはこのようにループすればよい。

 なお、Python 3.10からはsys.orig_argv属性が追加されている。こちらはPythonの処理系に渡される全てのコマンドライン引数が格納される。

import sys

print('sys.orig_argv:', sys.orig_argv)


 以下にこのファイル(bar.pyファイル)を実行する例を示す。

> python3 -i bar.py foo bar baz
sys.orig_argv: ['C:\\Users\\user\\AppData\\Local\\Programs\\Python\\Python310\\python.exe',
'-i', 'bar.py', 'foo', 'bar', 'baz']
>>>  # python3コマンドに与えた-iオプションにより対話環境が起動した



コマンドライン引数を位置引数として扱う

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。