python入門講座 | pythonを使ってみよう3-6(コマンドライン引数を取るスクリプトの書き方)[第11回]

アラサーOLのためのpython入門講座
コマンドライン引数を取ることで、プログラムへの入力を都度変更することができます。スクリプトの編集は不要です。

Ciao!みなさんこんにちは!このブログでは主に
(1)pythonデータ解析,
(2)DTM音楽作成,
(3)お料理,
(4)博士転職
の4つのトピックについて発信しています。

今回は「アラサーOLのためのpython入門講座」です!
この講座では、プログラミング初心者アラサーOLのMi坊さんに、pythonを学習する上でのアドバイスを行います!
パソコンもプログラミングも初心者だけど、プログラミングができるようになりたい!」という方のためにstep-by-stepで解説していきます。

今日もPythonのスクリプト(ソースコード)の書き方をご紹介します!
Pythonスクリプトは、複雑な処理を行いたい場合や同じ処理を繰り返したい場合などに便利です。
今回はPythonスクリプトを実行する際に「引数(コマンドライン引数)」を取るための方法をご紹介します。
コマンドライン引数を取ることで、Pythonスクリプトへの入力を自由に変えることができます。
同じ処理を別の入力に対して行いたい場合に必要な方法です!

コマンドライン引数を取るスクリプトを書いてみることで、Pythonプログラミングを習得した先に何ができるのか、ゴールイメージを持つことができます!
一緒にやってみましょう!

Kaiko
Kaiko

この記事はこんな人におすすめ

  • 初心者だけどpythonを始めた!
  • とりあえずpythonを使ってみたい!
  • 本格的なpythonの動かし方を知りたい!

Abstract | コマンドライン引数で入力を自在に変えられる

コマンドライン引数を取るスクリプトにしておくことで、スクリプトの中身を編集することなく、プログラムへの入力を自由に変更することができます。
プログラミングでは予めスクリプトにコーディングしておいた処理しか行うことができません。したがって、通常は何かを変えようと思ったらスクリプトを編集する必要があります。
これではさすがに面倒なので、スクリプトを実行する際に入力を外から与えることができます。
そのための機能がコマンドライン引数です。

実行時にコマンドライン引数を入力することで、スクリプトに書かれた処理をその入力に対して行うことができます。
例えば、2つの値(例えば2と3)について何らかの計算を行うスクリプトを書いたとしましょう。
2つの値をスクリプトの中で定義している場合は、2と3以外の数字で計算したいときにいちいちスクリプトを書き換えなければなりません。
しかし、2つの値をコマンドライン引数として与えられるようにすることで、2つの値を自由に変えて入力することができるようになります。



Background | プログラムとコマンドライン引数

プログラミングでは入力となるファイルや数値を自由に変えたい場合があります。
プログラミングでは予めコーディングされた処理しか行えないので、入力を変える場合にはいちいちスクリプトを編集しないといけないように思えますが、そんな面倒なことはしたくないですよね。

このようなときに便利なのがコマンドライン引数です。
コマンドライン引数とはターミナルからPythonスクリプトを実行する際に

python hello_arguments.py FILE STR VAR1 VAR2

のように、実行するPythonスクリプトの後ろに半角スペースを開けて追加される文字列のことです。
この例では

  • FILE
  • STR
  • VAR1
  • VAR2

という文字列がコマンドライン引数です。

コマンドライン引数を付けて実行することで、これらコマンドライン引数の値をPythonスクリプトへの入力として渡すことができます。
これによって、Pythonスクリプトに書いておいた処理をそれら入力に対して行うことができます。
スクリプトの中身を書き換えずに入力を自由に変更することができます

引数を取得する方法には

  • sys.argvを使う方法
  • argparseを使う方法

の2つがあります。
「sys.argv」は複雑なことはできませんが、コーディングが単純で何をやっているのかわかりやすいです。
「argparse」の方が拡張性が高く実戦的ですがコーディングが若干複雑になります。
私は普段プログラミングするときはargparseを使っています。

今回の記事では「sys.argv」を使う方法を紹介します。
こちらの方法のほうがコーディングがシンプルに済みますし、やっていることを理解しやすいので「引数のとり方」の紹介としてこちらを取り上げます。
「argparse」を使う方法は機会があればそのうち解説します!



Method | コマンドライン引数を取るスクリプトを書いてみよう

本記事では、練習として「hello_arguments.py」というスクリプトを書きましょう。
前回記事「python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)」で作成した「hello_arithmetic.py」の発展型です。
一つづつ説明するので真似してやってみてください!

作成するスクリプトの概要

今回は、前回記事「python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)」で作成した「hello_arithmetic.py」を改変します。
hello_arithmetic.pyでは、”p_input”という辞書型変数に格納されたファイル名[‘FILE’]、文字列[‘STR’]、数値1[‘VAR1’]、数値2[‘VAR2’]を使って、ファイルの存在を確かめたり、文字列を表示したり四則演算を行いました。

今回作成するスクリプトでは、”p_input”に定義されていた数値を引数として外部から与えられるようにしてみましょう。
ファイル名[‘FILE’]、文字列[‘STR’]、数値1[‘VAR1’]、数値2[‘VAR2’]の4つの引数を外部から与えます。
ターミナルからスクリプトを実行する際、

python hello_arguments.py FILE STR VAR1 VAR2

のように実行することになります。

準備 | 新規ファイルの作成

Pythonスクリプトを書く準備をしていきましょう。
Pythonの練習用ファイルを格納しているディレクトリに移動し、新規Pythonスクリプトファイルを作際します。

下準備1 | ディレクトリの移動

まずはいつものようにPython練習用ディレクトリに移動します。
以前「アラサーOL | pythonを使ってみよう3-3(簡単なpythonスクリプトの書き方と実行方法)」と同様、ホーム直下のpython練習用ディレクトリ「python_practice」を使います。
今回もここにスクリプトファイルを作成します。

操作はターミナルで行いましょう。
ターミナルを立ち上げたら

cd ~/python_practice

でpython練習用ディレクトリに移動します。
ターミナルの立ち上げ方は過去の記事「アラサーOL|ターミナル操作入門(pythonを学び始める前に1)」をご覧ください。

下準備2 | ファイルの新規作成

まずは新規ファイルを作成しましょう。
前回記事「python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)」で作成した「hello_arithmetic.py」をテンプレにして作成してみましょう。
ターミナルでファイルをコピーペーストしましょう。
以下のコマンドでコピーペーストできます。

cp hello_arithmetic.py hello_arguments.py

次に、

atom hello_arguments.py

を実行して「hello_arguments.py」をAtomエディタで開きます。
このファイルを編集し、引数(argument)として与えた文字列を表示させる「Hello」に続いて表示させたり、ファイルの存在を確認したり、四則演算をするプログラムを作りましょう。



メタ情報の更新

まずはメタ情報を適切に更新しましょう。
別のファイルをコピペしたので、いまはメタ情報が不適切になっているはずです。
プログラムの概要がわかるように正しく書き直しましょう。
例えば下記のように書いてみましょう。

#!/usr/bin/env python

# -*- coding: utf-8 -*-

# ------------------------- #
# Created By Kaiko on 20210705
# Edit History
#    20210705: File created by Kaiko from "hello_arithmetic.py"
# ------------------------- #

"""
Purpose of the script
    1. To learn how to run Python using a script
    2. To print "Hello, world"
    3. To test arithmetic calculation
    4. To learn how to get arguments

How to use the script
    python hello_arguments.py args1 arg2 arg3 arg4
"""

「hello_arithmetic.py」からの変更点がいくつかあります。
“Edit History”や”How to use the script”のところが変わっていますね。
このスクリプトは引数を4つ取るのでarg1からarg4を取るということがわかるように

How to use the script
    python hello_arguments.py args1 arg2 arg3 arg4

としています。

メタ情報以外の箇所は変更する必要はありません。
「hello_arithmetic.py」にあったものをそのまま使いましょう。

  • print_time_and_file_existence
  • print_hello_hogehoge
  • calc_arithmetic

の3つの関数はそのまま使います。



コマンドライン引数を取得する関数の追加

コマンドライン引数を取得する関数を追加しましょう。
main関数の前に「get_argv」という名前の関数を書きましょう。
ちなみにargvとは”argument vector”の略で「引数の配列」という意味です。

以下のような関数を書いてみてください。

# - function to obtain command-line argumets using sys.argv - #
def get_argv():
    """
    arguments:
        None
    returns:
        0
    """
    # - define global variable - #
    global p_input

    # - print current frame - #
    print(' - %s -' % (sys._getframe().f_code.co_name)) # use library 'sys'

    # - get arguments - #
    argv = sys.argv   # run-time inputs
    argc = len(argv)  # length of inputs = number of args + 1

    # - print usage if the number of argument is equal to or less than 4 - #
    if(argc <= 4):
        print('Usage:')
        print('python %s FILE STR VAR1 VAR2' % (argv[0]))
        exit(1) # exit if enough arguments are not given

    # - loop for number of arguments - #
    keys_p_input = list(p_input.keys()) # keys for p_input as list
    for i in range(min(argc, len(keys_p_input))):
        # - declare the argument - #
        print(keys_p_input[i], ':', argv[i+1])
        # - change value in p_input - #
        p_input[keys_p_input[i]] = argv[i+1]

    # - end - #
    return 1
#--#

内容としてはかなり高度です。
一応一つずつ解説しますが、全て理解しなくて構いません。

global変数の宣言 | global p_input

関数のはじめの方に

global p_input

というのがあります。
これはこのスクリプトの最初の方、関数の外で定義された変数を呼び出すおまじないです。
厳密には、どの関数にも属さない場所で定義されたグローバル変数を呼び出すおまじないです。
何らかの関数の中で定義された変数をその関数のローカル変数、外で定義された変数をグローバル変数と言います。

通常、関数の中と外との変数のやり取りは、

  • 引数で与える
  • returnで取り出す

以外の方法はありません(詳しくは前回記事「python入門講座 | pythonを使ってみよう3-5(pythonスクリプトを書いてみよう)」の関数の説明を見てください)。
しかし、「global」というおまじないを使うと、引数で与えなくても関数の外で定義されたグローバル変数を呼び出すことができます。
単に呼び出して値を参照するだけでなく、値を代入して書き換えることができます。

get_argvsという関数では、p_inputというグローバル変数の値を、プログラム実行時の引数として入力された数値に書き換えるという作業をしています。
“global p_input”というおまじないを使うことによって、グローバル変数であるp_inputを召喚し、参照および更新ができる状態にしているのです。

コマンドライン引数の取得 | argv = sys.argv

関数の中央あたり、”# – get arguments – #”というコメント行の次に

argv = sys.argv   # run-time inputs

というのがあります。
この行でコマンドライン引数を取得しています。
はじめにimportしておいたsysというライブラリにはコマンドライン引数を取得する”arvg”というメソッドがあります(メソッドが何かはここではスルーしてください。そういう名前の機能です)。
“sys.argv”のように呼び出すとコマンドライン引数のリストが生成されます。
ここでは”argv”という変数にコマンドライン引数のリストを格納しています。

すぐ下の

argc = len(argv)  # length of inputs = number of args + 1

ではargvというリストの要素数を数えています。
“argc”というのは”argument count”の略で、「引数の数」という意味です。
ちなみに、 argvもargcももともとはC言語で使われる用語です。

argcはインラインコメントにある通り、「コマンドライン引数 + 1」です。
これは、argvの最初の要素(argv[0])がスクリプトのファイル名だからです。

python hello_arguments.py FILE STR VAR1 VAR2

とスクリプトを実行した場合、

  • argv[0]: ‘hello_arguments.py’
  • argv[1]: ‘FILE’
  • argv[2]: ‘STR’
  • argv[3]: ‘VAR1’
  • argv[4]: ‘VAR2’

のようにargvに格納されます。
argvの要素の数は上記の5つなので、argcは5となります。
また、与えられたコマンドライン引数は全て文字列として格納されます。

コマンドライン引数が不足しているときの処理

関数後半の

    # - print usage if the number of argument is equal to or less than 4 - #
    if(argc <= 4):
        print('Usage:')
        print('python %s FILE STR VAR1 VAR2' % (argv[0]))
        exit(1) # exit if enough arguments are not given

では、コマンドライン引数が不足しているときの動作を書いています。

このプログラムには4つのコマンドライン引数

  1. 存在を確認する対象のファイル: FILE
  2. Helloの後に表示する文字列: STR
  3. 四則演算の数値1: VAR1
  4. 四則演算の数値2: VAR2

が必要です。
4つのコマンドライン引数が全て入力された場合、argcは5になります。

argcが4以下の場合にはコマンドライン引数が全て入力されなかったことになります。
例えば

python hello_arguments.py FILE STR VAR1

と実行すると、argvの値は

  • argv[0]: ‘hello_arguments.py’
  • argv[1]: ‘FILE’
  • argv[2]: ‘STR’
  • argv[3]: ‘VAR1’

と4つの要素しかないためargcは4となります。
このような場合には「コマンドラインを引数を4つ入力してくださいね」と使い方を表示してプログラムを終了することにしています。
print文が2つあるところが使い方の表示、”exit(1)”という箇所がプログラム終了の部分です。

コマンドライン引数の変数への格納

関数の最後

    # - loop for number of arguments - #
    keys_p_input = list(p_input.keys()) # keys for p_input as list
    for i in range(min(argc, len(keys_p_input))):
        # - declare the argument - #
        print(keys_p_input[i], ':', argv[i+1])
        # - change value in p_input - #
        p_input[keys_p_input[i]] = argv[i+1]

では、グローバル変数p_inputにコマンドライン引数argvの内容を格納しています。

はじめの

keys_p_input = list(p_input.keys()) # keys for p_input as list

では、辞書型変数であるp_inputのkeyをリストとして出力しています。いまは何を言っているかわからなくてOKです。別の機会に説明します。
辞書型変数は”p_input[key]”という形で使用して値を参照したり格納します。
keyは複数取ることができ、ここではスクリプトの最初の方で’FILE’, ‘STR’, ‘VAR1’, ‘VAR2’が定義されています。
上記のようにコーディングことで、keys_p_inputに[‘FILE’, ‘STR’, ‘VAR1’, ‘VAR2’]という順番でkeyが格納されます。

その後の

for i in range(min(argc, len(keys_p_input))):

から始まるfor文の部分では、コマンドライン引数の数かp_inputのkeyの数どちらかの小さい方の数だけループが回ります。
余談ですが、実はこのようにどちらか小さい方だけ回るようにしているので、コマンドライン引数が不足していてもプログラム自体は動くようにしています。
なので、本来前述のコマンドライン引数が4つ以下なら使い方を表示してプログラムを終了するという処理は不要です。
ただ、必ずコマンドライン引数を4つ入力することにした方が教材としてわかりやすいのでこの処理を入れました。

このループ処理によってp_inputにコマンドライン引数(argv)の値が順番に格納されていきます。

  • p_input[‘FILE’]にargv[1]が
  • p_input[‘STR’]にargv[2]が
  • p_input[‘VAR1’]にargv[3]が
  • p_input[‘VAR2’]にargv[4]が

格納されるようになっています。



main関数の編集

main関数を編集し、先程追加したget_argvという関数を呼び出してコマンドライン引数をp_inputに反映させます。
main関数は以下のようにしましょう。

#-------------------------#
# main func
if __name__ == '__main__':
    # - get argvs - #
    get_argv()

    # - print p_input - #
    print(p_input)

    # - use function 1 - #
    ret = print_time_and_file_existence(p_input['FILE'])

    # - use function 2 - #
    ret = print_hello_hogehoge(p_input['STR'])

    # - use function 3 - #
    ret = calc_arithmetic(float(p_input['VAR1']), float(p_input['VAR2']))

一番最初にget_argvを使っています。
この関数は引数無しで動くのでget_argv()のようにカッコの中は空です。
get_argvを使った後にp_inputを表示(print(p_input))して確認しています。
そのあとの、print_time_and_file_existenceとprint_hello_hogehogeを使うところはコピー元のスクリプト「hello_arithmetic.py」から変わっていません。

最後のcalc_arithmetic関数を呼び出すところは、2つの引数をfloat型に変換しています。
ここは「hello_arithmetic.py」から変わっています。
p_input[‘VAR1’], p_input[‘VAR2’]にはコマンドライン引数の値(argv[3], argv[4])が文字列として入っています。
calc_arithmeticでは四則演算を行うので、float型もしくはint型でないといけません。
ここでは文字列から小数点が扱えるfloat型に変換しています。



作成例

ここまでできたら「hello_arguments.py」は完成です。
参考にhello_arguments.pyの作成例をこちらに置いておきます。
もしわからないところやうまくいかなければ参照してください。



Result | コマンドライン引数付きで実行してみよう

作成したスクリプトをコマンドライン引数付きで実行してみましょう!
ターミナルを開いてpython練習用のディレクトリ(hello_arguments.pyが存在する場所)に移動しましょう。
Atomエディタを開いたターミナルが残っていればそれで構いません。

引数無しで実行して挙動を確認

まずはターミナルで以下のように、引数無しで実行してみましょう。

python hello_arguments.py

すると、引数が不足しているときには使い方を表示してプログラムを終了することになっているので、

 - get_argv -
Usage:
python hello_arguments.py FILE STR VAR1 VAR2

と表示されて終わります。

引数を与えて挙動を確認

次に引数を適当に与えてみましょう。

python hello_arguments.py hello_arithmetic.py kaiko 2 3

と実行してみてください。
以下のように表示されるはずです。

 - get_argv -
FILE : hello_arithmetic.py
STR : kaiko
VAR1 : 2
VAR2 : 3
{'FILE': 'hello_arithmetic.py', 'STR': 'kaiko', 'VAR1': '2', 'VAR2': '3'}
 - print_time_and_file_existence -
 Time: 2021-07-07 22:13:00.027637
 File "hello_arithmetic.py" exists. Result = True
 - print_hello_hogehoge -
 Hello, kaiko
 - calc_arithmetic -
 var1 =  2.0
 var2 =  3.0
 var1 + var2 =  5.0
 var1 - var2 =  -1.0
 var1 * var2 =  6.0
 var1 / var2 =  0.6666666666666666
 var1 // var2 =  0.0
 var1 % var2 =  2.0
 var1 ** var2 =  8.0


最初にget_argvが動いて、p_inputの内容{‘FILE’: ‘hello_arithmetic.py’, ‘STR’: ‘kaiko’, ‘VAR1’: ‘2’, ‘VAR2’: ‘3’}が表示されます。
次に、print_time_and_file_existenceで「hello_arguments.py」というファイルの存在が確認され、print_hello_hogehogeで「Hello, kaiko」が表示されます。
最後にcalc_arithmeticで2と3の四則演算が表示されます。

引数をいろいろ変えて試してみる

引数を変えて実行してみましょう。
4つの好きなように変えて、動作を確認してみましょう!



Discussion | コマンドライン引数を取るメリット

コマンドラインから実行する際に引数を与えられるようにしておくことで同じ処理を繰り返し、好きな値に変えて実行できます。
テスト用のプログラムなので、

  1. ファイルの存在を確認する
  2. Helloに続いて文字列を出力する
  3. 四則演算する

という単純なことしかできませんが、プログラムの中身がもっと実用的だったらどうでしょう?
例えば、2つのファイルを読み込んで照合したり、結合したりする処理ならみなさんのお仕事でも該当する業務があるのではないでしょうか?
他にはマスターファイルと部分的に更新されたファイルがあって、マスターファイルに更新部分を反映したいなどということもあるでしょう。

このような操作を毎日、異なる名前のファイルに対して行う場合にはコマンドライン引数を取るプログラムが有効です。
行いたい操作をスクリプトにプログラムしておき、入力ファイルはコマンドライン引数として与えることで、コマンド一行ですべての操作を完了できます。
作業の自動化を行いたい場合、コマンドライン引数を取るスクリプトの書き方を覚えるとプログラミングで実現することができます!



Conclusion | まとめ

最後までご覧頂きありがとうございます!
コマンドライン引数を取るPythonスクリプトの書き方をご紹介しました!

コマンドライン引数を与えられるようにすることで、プログラムへの入力を都度変えることができます。
同じ処理を別の入力ファイルに対して行いたい場合などにコマンドライン引数を取るPythonスクリプトが役に立ちます。
今回の内容自体は入門講座を逸脱しているので理解できなくても問題ありません!
「こういうことができるのね」というPython習得の先のイメージを持ってもらうことが目的です!
イメージを持った上で地道に習得していきましょう!

以上「python入門講座 | pythonを使ってみよう3-6(引数を取るスクリプトの書き方)」でした!
またお会いしましょう!Ciao!

コメント

タイトルとURLをコピーしました