【Watson/python】IBM Watson Visual Recognitionを使って、pythonスクリプト上で画像分類を行う
IBM Watson Visual Recognition
IBM Watson Visual Recognitionは、IBMが提供するDeep Learningを利用した画像認識サービスです。
IBM Cloud上で利用することができ、APIやSDK経由で画像データの分類を行うことができます。
今回はpython用Watson Visual Recognitionモジュールを用いて画像分類をやってみます。
Usage
IBM Cloudアカウントの取得
まずはIBM Cloudのアカウントを取得しましょう。
下記記事に取得方法を記載してあります。
Visual Recognition サービスを作成する
次にIBM Cloud上でVisual Recognitionのサービスを作成します。
IBM Cloudダッシュボード画面にて、画面右上の「リソースの作成」ボタンを押します。
すると利用できるリソース一覧が表示されるので、一番下の「Watson」の項目一覧にある「Visual Recognition」をクリック。
遷移先画面の右下にある「作成」ボタンをクリック。
するとVisual Recognitionサービス詳細画面に移動します。
ここで表示されるAPIキーは後ほどpythonスクリプト上で利用します。
Watson Visual Recognitinoモジュールをインストール
pip
を使い、python用Visual Recognitionモジュールをインストールします。
$ pip install --upgrade "watson-developer-cloud>=1.4.0"
これで準備完了です。
Source
以下にVisual Recognitionを利用した画像分類のスクリプト例を示します。
このスクリプトは、一枚の画像をVisual Recognitionに送信し、
その分類結果をJSON形式で標準出力する簡単なものです。
{API_KEY}
にはVisual Recognition サービス作成時に取得したAPIキーを入力してください。
from watson_developer_cloud import VisualRecognitionV3, WatsonApiException def recognize(): WVR_VERSION = '2016-05-20' WVR_API_KEY = '{API_KEY}' FILE_PATH = 'cat.jpg' # 分類対象画像ファイル try: visual_recognition = VisualRecognitionV3(WVR_VERSION, iam_api_key=WVR_API_KEY) with open( FILE_PATH , 'rb') as image: # クラス分類:今回はすでに用意された分類器を使用 results = visual_recognition.classify(images_file=image, classifier_ids=['default']) print(results) except WatsonApiException as ex: print(ex.message) if __name__ == '__main__': recognize()
Demo
試しに、以下の画像を分類してみます。
すると、以下ようなJSON形式で結果が返されます。
今回は猫の画像を上げたので、「猫」クラスのスコアや「動物」クラスのスコアが高いのがわかります。
{'images': [{'classifiers': [{'classifier_id': 'default', 'name': 'default', 'classes': [{'class': 'cat', 'score': 0.893, 'type_hierarchy': '/animal/mammal/carnivore/feline/cat'}, {'class': 'feline', 'score': 0.905}, {'class': 'carnivore', 'score': 0.905}, {'class': 'mammal', 'score': 0.906}, {'class': 'animal', 'score': 0.953}, {'class': 'tabby cat', 'score': 0.548, 'type_hierarchy': '/animal/mammal/carnivore/feline/cat/domestic cat/tabby cat'}, {'class': 'domestic cat', 'score': 0.713}, {'class': 'kitten', 'score': 0.5, 'type_hierarchy': '/animal/young/kitten'}, {'class': 'young', 'score': 0.508}, {'class': 'ash grey color', 'score': 0.849}, {'class': 'gray color', 'score': 0.571}]}], 'image': '../res/cat.jpg'}], 'images_processed': 1, 'custom_classes': 0}
参考
【python】pipでファイル内に記述した複数モジュールを一括インストールする
メモ。
pip install -r
で、ファイルに記述したモジュールを一括してインストールできる。
# インストールしたいモジュールを記述したファイル $ cat hoge.txt asn1crypto==0.23.0 bleach==1.5.0 certifi==2017.11.5 cffi==1.11.2 chardet==3.0.4 cryptography==2.1.3 cycler==0.10.0 ... # 一括インストール $ pip install -r hoge.txt Collecting asn1crypto==0.23.0 (from -r hoge.txt (line 1)) ...
入れたいモジュールを一気に入れられるのは便利だし、スクリプトを共有するときに依存モジュールを外部にまとめて書いておいてスクリプト内で自動一括インストール...みたいなことができるのも便利。
【Watson】Watson Studio でMNIST手書き文字認識を行う②【モデル学習・推論】
前回までのあらすじ
前回の記事では、Watson Studioのセットアップを行いました。 今回の記事では、実際にMNISTデータセットを使って手書き文字の学習とクラス分類を行います。
MNISTとは
MNISTとは、パターン認識や機械学習の研究で頻繁に用いられる手書き文字画像データです。
手書き文字といってもアルファベットやひらがながすべて網羅されている・・・というわけではなく、0から9までの10種類の手書き文字のみから構成されています。データセットとしてシンプルでありながら十分な数のデータ数があるため、少し前はアルゴリズム・手法の性能を図るためのスタンダードなデータセットとして、現在は機械学習のHello,World的データセットとして用いられています。
それでは、早速Watson StudioでMNISTを学習してみましょう!
Usage
データセットを取得する
まずはデータがなければ始まらないので、MNIST手書き文字データセットをダウンロードします。
今回はWatson Studioに読み込ませるMNISTがほしいので、こちらからダウンロードします。
遷移先のページ右上にダウンロードボタンがあるので、クリックしてMNISTのpklファイルをダウンロードしましょう。
MNIST-pkl.zipがダウンロードできるので、解凍して
- mnist-keras-test.pkl
- mnist-keras-train.pkl
- mnist-keras-valid.pkl
- mnist-keras-test-payload.json
があることを確認します。
Watson Studioプロジェクトを作成する
前回の記事で作成したWatson Studioサービスのページに遷移し、「Get Started」をクリックします。
するとWatson Studioのトップページに遷移するので「Get started with key tasks」メニューの「New project」ボタンをクリックしてください。
するとプロジェクトの種類を選択するダイアログが出現します。
今回は深層学習を行うので、「Deep Learning」を洗濯して「OK」を押してください。
画面遷移時にMachine Learning・Object Storageサービスの作成が行われます(未作成の場合)。インストールしたいスペースを聞かれるので、Watson Studioと同じスペースを選択してください。
次にプロジェクト詳細を定義します。
先程作成したMachine Learning・Object Storageサービスが右側に表示されているか確認してください。設定されていなければ「Reload」ボタンを押してみてください。
問題がなければ「create」を押します。
データセットをWatson Studioに読み込ませる
ストレージが用意できたので、ダウンロードしたデータセットをWatson Studioにアップロードします。
Watson Studio画面トップのメニューバーのプルダウン「Service」をクリックし、次いで「Data Services」をクリックします。
「Cloud Object Storage」メニュー中にある、先ほど作成したObject Storageサービスをクリック。
「バケットの作成」をクリック。
バケット作成ダイアログが出現するので、名前を入力してください。
念の為、ロケーションをus-geo
にします。その後「作成」をクリック。
するとデータをアップロードする画面が表示されます。
右上の「アップロード」ボタンをクリックしてファイルダイアログを開き、ダウンロードしたpklファイルをすべてアップロードしてください。ドラッグ&ドロップでもアップロード可能です。
このような感じでアップロードできたらOK。
その後、同じように学習結果出力用のバケットも作成します。
先ほどとは別名のバケットをもう一つ作成してください。
データセットのアップロードは不要です。
モデルの作成
次に学習・クラス分類のためのモデルを作成します。
Watson Studioトップページに戻り、「Get started with key tasks」メニューの「New Modeler Flow」をクリック。
遷移先の画面の「From example」タブをクリック。
今回はすでに用意されているDeep Learningのモデルを使います。
遷移したら、「Single Convolution layer on MNIST」のカードメニューをクリックし、「Project」が冒頭で作成したプロジェクト担っていることを確認して「Create」をくりっくしてください。
すると何やら数珠つなぎになった図が表示されます。
これはDeep Learningで用いられる「ニューラルネットワーク」と呼ばれる学習モデル(と最適化アルゴリズム等のオプション)の構成を表しており、これらの構成自体や、各パーツのパラメータを調整することでモデルの推論精度を高めたりすることができます。
一旦モデルの構造には変更を加えず、モデルの学習・テストに使うデータを設定します。
「Image Data」をダブルクリックすると下記サイドメニューが表示されるので、「Create a Connection」をクリックしてください。 Object Storageに接続します。
接続がうまく行った場合、「Data Connection」プルダウンが表示されるので、「Connect to project COS」を選択してください。すると続けて「Buckets」プルダウンが表示されるので、先程アップロードしたデータを含むバケットの名称を選択します。
その後「Train data file」「Test data file」「Validation data file」の所在を聞かれるのでそれぞれアップロード舌ファイルを選択し、「Close」をクリック。
最後にモデルを公開します。
画面右上のアップロードボタンをクリック。
ダイアログが出てくるので、名前が先ほど作成したモデル名であり、WML Instance の名前が冒頭で作成したサービスのものと一致するかチェックして「Publish」をクリック。
緑色の通知が出てきたら成功です!
さらにモデルの学習をすべく「or Train it in an experiment」をクリックしましょう。
モデルを学習する
先程のリンクをクリックすると、Experiment作成画面に遷移します。
Experimentはモデルの学習やテスト、精度推移の可視化などができる実験環境の単位を指します。
名前を入力し、作成したMachine Learning Serviceを選択してください。
その後下段の「Cloud Object Storage bucket for...」の「Select」ボタンをクリック。
「Cloud Object Storage connection」から「Connection to project COS」を選択し、 「Bucket containing training data」にはデータセットをアップロードしたバケットを、「Bucket for storing training results」には学習結果出力用のバケットを指定します。 指定したら「Select」をクリック。
新規experiment作成画面に戻り、「Add training definition」をクリックします。
先程作成したモデルを指定するため、「Existing training definition」タブ → 作成したモデル名を選択します。
すると「Training definition attributes」メニューが表示されます。 「Compute plan」はモデルの学習・テストに使う計算機リソースの構成のうち、どのGPUをどれだけ利用するかを選択します(台数や一台の性能が良いほどメモリや並列性が増し、学習やテストが高速になる)。「Hyperparameter optimization method」はモデルを学習する上でハイパパラメタ、つまり学習の際に予め設定しておくパラメータ初期値をどのように決定するかを指定します。今回は前者を「1 x NVIDIA® Tesla® K80 (2 GPU)」とし、校舎を「None」としました。選択したら「Select」をクリック。
「Create and Run」を押しましょう。
学習が開始されました!
遷移先の画面ではモデルの学習中の様子を見ることができます。 学習中のモデルの状態は「Queued」「In progress」「Completed」の順に遷移していき、「Completed」になると学習が終了したことを表します。
終了したら、詳細を見てみましょう。
学習が完了していることがわかります。
Logsには学習時のコンソールログも残されており、学習回数や、学習時点での学習データに対する分類精度等を見ることができます。
学習したモデルを保存する
学習したモデルは、保存して利用できるようになります。
先程の「Completed」状態にあるモデルの右端のメニュープルダウンから「Save model」を選択します。
保存用ページに遷移するので、名前を入力し、「Save」ボタンを押しましょう。
成功すると、緑色の通知が出ます。
「here」をクリックすることで、保存したモデルの詳細を見ることができます。 (またはメニューバー「Project」から作成したプロジェクトの「Assets」タブに遷移し、「Experiments」の項目で「Add Experiment」をクリックします)
保存したモデルをデプロイする
次に、保存したモデルをデプロイします。
デプロイすると、テストデータを使った検証や、API経由で分類器を提供することが可能になります。
今回はWeb Service としてデプロイしてみましょう。
先程のモデル詳細画面の「Deployments」タブをクリックします。
「Add Deployment」をクリック。
遷移先の画面
今回はテストデータセットを使った性能評価を行うので「Deployment type」の「Web Service」を選択します。 あとは名前を入力して「Save」をクリックします。
これだけでデプロイ完了です! 早速テストしてみましょう!
デプロイしたモデルをテストする
デプロイした結果作成されたDeployをクリックし、「Test」タブをクリックします。
冒頭でダウンロードしたmnist-keras-test-payload.json
の拡張子を.html
に変更します。
変更したあと、ブラウザでHTMLファイルを開きます。
開いたページのJSONファイルをコピーし、先程のDeploy画面のTestタブ内にあるフォームにペーストしてください。
「Predict」をクリックすると、クラス分類が開始されます。
元のJSONデータは数字の「7」を記した画像の濃淡値データを表しているので、帰ってきたクラス分類結果が「7」であれば分類成功です。
結果が帰ってきました!
レスポンスJSONのvalues
内配列の8番目の数値が1の場合、これは数字の7であるという分類結果になります。
上記画像では分類に成功していることがわかります。
まとめ
いかがだったでしょうか。
今回はMNIST分類の簡単な学習とテストを行いましたが、より複雑なモデルの構築、学習、テストももちろん可能です。
pythonスクリプトへのエクスポートなどもできるので、これからどんどん試していこうと思います。
参考
【Java】Jacksonで任意形式のJSONをパースする
Jackson
Jacksonについては以下の記事を参照。
多様なJSONの構造
前回の記事で、JSONをMapオブジェクトにする記事を書きました。
JacksonではJSONファイルやStringオブジェクトとしてのJSONをJavaクラスのオブジェクトに簡単にマッピングしてくれます。
この記事のように、JSONをMapオブジェクトに変換することも可能です。
しかし、各プロパティの値が階層的にオブジェクトになっている場合は、Map<String, Object>
でごまかすか、
Map<String,Object>
やMap<String, Map<String, Object>>>
のようにわかる範囲までジェネリクス型を明示してあげる必要があります。
更に後者の場合、各プロパティの階層レベルがすべて等しくなければパースに失敗します。
コンテナとなるJavaクラスを定義することでもパースが可能ですが、JSONのパターンの数だけJavaクラスを定義しなければならなくなり、面倒です (新しいパターンが増えたらまたクラスを定義する必要もあります)。
任意の構造を持つJSONを読み込む
Jacksonでは、ObjectMapper
クラスのメソッドreadTree()
を用いることでこの問題を解決できます。
String json = "{ ... }"; // JSON形式文字列 ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json);
readTree()
はJsonNode
オブジェクトを返します。
JsonNode
はJSONを木構造に見立てたときのノード(枝)として振る舞い、ノードに格納された値を参照したり、小ノードを参照することができます。
Source
JSON
{ "hoge": { "fuga": 1, "piyo": 2 }, "foo": ["bar", "bow"] }
Source
package com.company; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import jdk.nashorn.internal.runtime.regexp.JoniRegExp; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.spec.ECParameterSpec; public class Main { public static void main(String[] args) { String json = readJsonAsString("res/hoge.json"); if (json != null) { try { readJsonNode(json); } catch (IOException e) { e.printStackTrace(); } } } /** * * readTree()でJsonNodeインスタンスを作成 * */ private static void readJsonNode(String json) throws IOException { ObjectMapper mapper = new ObjectMapper(); // JSON文字列を読み込み、JsonNodeオブジェクトに変換(Fileやbyte[]も引数に取れる) JsonNode root = mapper.readTree(json); // get()で指定したキーに対応するJsonNodeを取得できる System.out.println(root.get("hoge")); // {"fuga":1,"piyo":2} // 階層的にアクセス可能 System.out.println(root.get("hoge").get("fuga")); // 1 // 配列にアクセスするときは添字をわたす System.out.println(root.get("foo").get(0)); // "bar" // 値を特定の基本型に変換して取得可能 System.out.println(root.get("hoge").get("piyo").asInt()); // 2 System.out.println(root.get("hoge").get("piyo").asDouble()); // 2.0 System.out.println(root.get("hoge").get("piyo").asBoolean()); // true // toString()でJSON全体を文字列として取得 System.out.println(root.toString()); // {"hoge":{"fuga":1,"piyo":2},"foo":["bar","bow"]} } /** * * JSONファイルを一つの文字列オブジェクトとして読み込み * */ private static String readJsonAsString(String filename) { ObjectMapper mapper = new ObjectMapper(); try { BufferedReader reader = new BufferedReader(new FileReader(new File(filename))); String line = null; StringBuilder builder = new StringBuilder(); while ((line = reader.readLine()) != null) { builder.append(line); } return builder.toString(); } catch (IOException e) { e.printStackTrace(); } return null; } }
参考
【Java】JacksonでJson文字列をMapオブジェクトに変換する
Jackson
Jacksonについてはこちら。
JacksonはJavaのライブラリで、JavaオブジェクトをJSON形式にしたり、その逆のこともできます。もちろんJSONファイルへの読み書きも可能です。
JSONをMapオブジェクトに変換する
Jacksonでは、JSON文字列をJavaオブジェクトに変換することができますが、 変換の方法の一つに、JSONのプロパティと同じ名称のプロパティを持つJavaクラスを用意するやり方があります。
public class JSONResponse { private String name; private String age; }
// JSON文字列であるjsonをJSONResponse型オブジェクトに変換 JSONResponse response = mapper.readValue(json, JSONResponse.class);
JSONのプロパティがいつも同じであれば問題はないのですが、
例えば異なるAPIのレスポンスを処理する場合などに、レスポンスごとの個別のコンテナクラスを作成する必要があります。
そんなときは、JSONをMapオブジェクトに変換してしまいましょう。
JacksonのTypeReference
オブジェクトを利用することでJSONからMap型オブジェクトを生成することができます。
TypeReference<HashMap<String, String>> reference = new TypeReference<HashMap<String, String>>() {};
Map<String, String> map = mapper.readValue(json, reference);
【python】コマンドラインパーサclick
clickとは
Welcome to the Click Documentation — Click Documentation (5.0)
click
はpythonのコマンドライン解析用モジュールです。
pythonスクリプトをCLI上で実行したときに、コマンドライン引数のラベルを定義したり、ヘルプを表示するなどの機能を提供します。
前回の記事ではpython標準のコマンドラインパーサargparser
を紹介しました。
今回はサードパーティ製のコマンドラインパーサclick
の使用法を軽く紹介したいと思います。
Usage
pip
でclick
をインストールします。
$ pip install click
これだけでOKです!
Source
基本形
click
では、基本的に関数やメソッドにアノテーションを付加していきます。
ここがargparser
との大きな違いですね。
最初に、click
モジュールをインポートし、呼び出すトップレベルの関数に@click.command()
アノテーションをつけてみましょう。
import click @click.command() def main(): print() if __name__ == '__main__': main()
$ python main.py --help Usage: main.py [OPTIONS] Options: --help Show this message and exit.
これだけで、コマンドライン上でのヘルプメッセージがサポートされていることがわかります。
必須引数の設定
指定が必須な引数の設定は、@click.argument()
アノテーションで行います。
import click @click.command() @click.argument("arg1") # 必須パラメータ定義 def main(arg1): print(arg1) if __name__ == '__main__': main()
@click.argument()
で指定した引数と関数の仮引数名(ここではarg1
)は一致している必要があります。渡された引数はこの仮引数arg1
に格納され、関数やメソッド内で利用することができます。
# ヘルプメッセージに引数情報が追加される $ python main.py --help Usage: main.py [OPTIONS] ARG1 Options: --help Show this message and exit. # NG(必須引数を指定していない) $ python main.py Usage: main.py [OPTIONS] ARG1 Error: Missing argument "arg1". # OK $ python main.py test test
引数を設定すると、ヘルプメッセージに引数の情報が追加されます。
必須引数はその名の通り必ず設定されている必要があります。
設定されていない場合、click
がエラーを送出します。
また指定した引数は指定順にコマンドライン引数値と対応付けされます。
例えば、上記の例ではarg1
というコマンドライン引数がtest
という値と対応付けされています。
オプション引数の指定
@click.option()
で任意引数も定義することが可能です。
@click.command() @click.option("--opt") def main(option): print(option)
オプションの場合、オプション引数名が関数の引数名とハイフンを除いて一致している必要があります。
またオプション引数を指定した場合、実行時に引数の頭に明示的に名前を指定する必要があります。
# NG : 値だけ渡すのはだめ $ python main.py option Usage: main.py [OPTIONS] Error: Got unexpected extra argument (option) # OK $ python main.py --opt option option # 指定しなくてもOK(指定しない場合、変数の値はNoneになる) $ python main.py None
またオプション引数名は短縮形を登録することができます。
# OK $ python main.py None # OK $ python main.py -o test test #OK $ python main.py --opt test test
型指定
引数の型指定がtype
オプションで可能です。
引数が指定型で解釈できない文字列の場合、エラーとなります。
import click @click.command() @click.argument("arg1", type=float) # 型指定 def main(arg1): print(arg1) if __name__ == '__main__': main()
# 引数がfloatで解釈できないので、エラー $ python main.py test Usage: main.py [OPTIONS] ARG1 Error: Invalid value for "arg1": test is not a valid floating point value # OK $ python main.py 3.14 3.14
複数値指定
一つの引数に複数の値をnargs
オプションで設定できます。
nargs
で設定した場合、引数はタプル値になります。
import click @click.command() @click.argument("arg1", type=float, nargs=3) def main(arg1): print(arg1) if __name__ == '__main__': main()
# NG 3つ引数が必要 $ python main.py 3.14 Error: argument arg1 takes 3 values # OK $ python main.py 3.14 1.23 4.44 (3.14, 1.23, 4.44)
またnargs=-1
を指定すると、任意の数の引数をとることができるようになります。
@click.argument("arg1", type=float, nargs=-1)
$ python main.py 3.14 1.23 4.44 9.81 111. (3.14, 1.23, 4.44, 9.81, 111.0)
ただし、別の引数が後ろに追加された場合、末尾の引数が他の引数に割り当てられます。
@click.command() @click.argument("arg1", type=float, nargs=-1) @click.argument("arg2", type=float) @click.argument("arg3", type=float) def main(arg1, arg2, arg3): print(arg1) print(arg2) print(arg3)
# 9.81は`arg2`に、111.0は`arg3`に割り当てられる $ python main.py 3.14 1.23 4.44 9.81 111. (3.14, 1.23, 4.44) 9.81 111.0
フラグ指定
@click.option
に限り、true/false
を表すフラグを定義することができます。
import click @click.command() @click.option("--is_read/--is_unread", default=False) def main(is_read): print(is_read) if __name__ == '__main__': main()
$ python main.py False $ python main.py --is_read True $ python main.py --is_unread False
まとめ
感想としては、コマンドライン引数の定義アノテーションで指定することで、
- どこでコマンドライン引数が定義されているのか
- どの関数が起点なのか(初期段階で呼ばれるのか)
- どのような設定なのか
がわかりやすく、また設定自体もシンプルで使いやすい印象でした。
参考
Welcome to the Click Documentation — Click Documentation (5.0)
【python】argparserでコマンドライン引数を解析する
argparser
16.4. argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.6.5 ドキュメント
argparser
はpython標準モジュールの一つで、pythonスクリプト実行時に受け取ったコマンドライン引数を解析するのに役立ちます。
例えば、ls
コマンドのように、引数無しで実行することもできれば、引数やオプションを与えることで挙動が変更するようなスクリプトを記述することができます。またargparser
を用いることで、デフォルトでヘルプメッセージを実装することができます。
Usage
基本形
argparser
を利用する基本形は以下になります。
import argparse parser = argparse.ArgumentParser("起動時メッセージ") args = parser.parse_args()
argparse
モジュールをインポートし、argparse.ArgumentParser
クラスのインスタンスを生成するだけです。これでコマンドライン引数を解析する準備が整いました。
以降、解析したコマンドライン引数はparse_args()
メソッドで取得することができます。
また、parse_args()
メソッドを呼び出した時点でスクリプトのヘルプコマンドが使えるようになります。
$ python hoge.py --help usage: 起動時メッセージ [-h] optional arguments: -h, --help show this help message and exit
必須コマンドライン引数の追加
引数の追加
引数の追加は、argparse.ArgumentParser
インスタンスのadd_argument()
メソッドを用いて行います。
import argparse parser = argparse.ArgumentParser("起動時メッセージ") parser.add_argument("arg1") args = parser.parse_args()
add_argument()
で追加した文字列は、コマンドライン引数のラベルとして扱われます。ラベルは追加された順に割り当てられます。
$ python hoge.py --help usage: 起動時メッセージ [-h] arg1 positional arguments: arg1 optional arguments: -h, --help show this help message and exit # 引数がないとエラー = 必須な引数 $ python hoge.py usage: 起動時メッセージ [-h] arg1 起動時メッセージ: error: the following arguments are required: arg1 # arg1が第一引数のラベルとして自動的に割り当てられる $ python hoge.py a Namespace(arg1='a')
引数の参照
引数への参照は、通常のオブジェクトのようにプロパティアクセスで可能です。
parser = argparse.ArgumentParser("起動時メッセージ") parser.add_argument("arg1") args = parser.parse_args() print(args.arg1)
$ python hoge.py 100 100
ヘルプメッセージ
add_argument()
の引数help
にはヘルプ表示時のメッセージを設定することができます。
parser.add_argument("arg1", help="arg1のヘルプメッセージ")
$ python hoge.py --help usage: 起動時メッセージ [-h] arg1 positional arguments: arg1 arg1のヘルプメッセージ optional arguments: -h, --help show this help message and exit
引数の型指定
引数には値の型も指定することができます。引数である文字列値を、指定された型にキャストしてくれます。
parser.add_argument("arg1", help="arg1のヘルプメッセージ", type=int)
# NG $ python hoge.py hoge usage: 起動時メッセージ [-h] arg1 起動時メッセージ: error: argument arg1: invalid int value: 'hoge' # OK $ python hoge.py 100 Namespace(arg1=100)
Optional引数
上記の引数は必ず指定しなければならないものでしたが、
引数名の頭に--
を付加することで任意引数とすることができます。
parser.add_argument("--arg1", help="arg1のヘルプメッセージ", type=int)
ただしoptional引数の場合、引数値の前に必ずラベルを明示する必要があります。
# optional引数は指定しなくても良い $ python hoge.py Namespace(arg1=None) # ただし、指定する際はラベルが必要 $ python hoge.py 100 usage: 起動時メッセージ [-h] [--arg1 ARG1] 起動時メッセージ: error: unrecognized arguments: 100 $ python hoge.py --arg1 100 Namespace(arg1=100)
optional引数の短縮形
多くのシェルコマンドと同様に、オプション指定の短縮形も設定することができます。
parser.add_argument("-a", "--arg1", help="arg1のヘルプメッセージ", type=int)
# OK $ python hoge.py Namespace(arg1=None) # OK $ python hoge.py --arg1 100 Namespace(arg1=100) # OK $ python hoge.py -a 100 Namespace(arg1=100)
argparser
はpythonコマンドラインパーサの基本形です。
慣れれば意外と使いやすいですし、何より標準なのでユーザに余計なパッケージを要求しないので一定の制約下では重宝します。
よりシンプルなコマンドラインパーサであるclickなどもおすすめなので、ぜひ使ってみることをおすすめします。
参考
16.4. argparse — コマンドラインオプション、引数、サブコマンドのパーサー — Python 3.6.5 ドキュメント