Pythonで一意な文字列を生成する
uuidモジュールで楽に生成できます
import uuid ustr = uuid.uuid4() print(ustr) print(ustr.hex)
$ py main.py 33536e0f-aef5-4dfc-9d5d-7c96c5139f0a 33536e0faef54dfc9d5d7c96c5139f0a
Argparseを使ったコマンドライン引数の管理
通常コマンドライン引数を扱うにはsys.argvを使います。
import sys args = sys.argv count = args[1] print(count)
$ py main.py 10 10
とてもシンプルですね。
ただ実際にちゃんとしたプログラムを組む場合、例えばコマンドライン引数が渡されなかった場合に例外にしたり、もしくはデフォルト値を設定したり、ハイフン始まりのオプション引数を用意したり、そういうことをやろうと思うとどんどん複雑になっていきます。
Argparseを使えばそういうったものをとても楽に実装することができます。
Argparse チュートリアル — Python 3.6.5 ドキュメント
とりあえず基礎的なものをいくつか実例で動作確認してみます。
ヘルプだけ用意された最小の例
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
$ py main.py -h usage: main.py [-h] optional arguments: -h, --help show this help message and exit $ py main.py --help usage: main.py [-h] optional arguments: -h, --help show this help message and exit
特に何も設定してない状態でも「-h」と「--help」が設定されます。
省略可能な引数を一つ設定する、省略時はデフォルト値が使われる。
import argparse parser = argparse.ArgumentParser() parser.add_argument("count", nargs='?', default=0) args = parser.parse_args() print(args.count)
$ py main.py 0 $ py main.py 10 10
nargsに'?'を設定すれば省略可能な引数を定義できます。defaultで省略時の値を設定できます。
オプション引数を設定する。
「-f」のようなハイフンで始まる独自のオプション引数を設定してみます。
import argparse parser = argparse.ArgumentParser() parser.add_argument("-f", "--foo") args = parser.parse_args() print(args.foo)
$ py main.py -h usage: main.py [-h] [-f FOO] optional arguments: -h, --help show this help message and exit -f FOO, --foo FOO
helpを見ると-fが追加されてるのが分かりますね。
$ py main.py -f 100 100 $ py main.py -f100 100 $ py main.py -f=100 100
この用に値を渡せます。
スペース空けたり空けなかったり、「=」を付けたり付けなかったりしてもどちらでも動作します。
型の変換をする
コマンドライン引数は全て文字列型になります。
import argparse parser = argparse.ArgumentParser() parser.add_argument("-f", "--foo") args = parser.parse_args() print(type(args.foo))
$ py main.py -f 100 <class 'str'>
これを例えば初めからint型にするにはtypeを使います
import argparse parser = argparse.ArgumentParser() parser.add_argument("-f", "--foo", type=int) args = parser.parse_args() print(type(args.foo)) print(args.foo)
$ py main.py -f 100 <class 'int'> 100
この状態でもし文字列を渡したりすると例外になります
$ py main.py -f aaa usage: main.py [-h] [-f FOO] main.py: error: argument -f/--foo: invalid int value: 'aaa'
またtypeは単に関数を指定するだけなので独自の関数を指定することで任意の変換処理をさせることができます。
import argparse def foo(s): return "["+s+"]"; parser = argparse.ArgumentParser() parser.add_argument("-f", "--foo", type=foo) args = parser.parse_args() print(args.foo)
$ py main.py -f aaa [aaa]
フラグ系のオプション引数を設定する。
値を設定する必要がない真偽値だけを持つオプション引数を設定してみます。
import argparse parser = argparse.ArgumentParser() parser.add_argument("--bar", action="store_true") args = parser.parse_args() print(args.bar)
$ py main.py False $ py main.py --bar True
他にも各引数にコメントを付けたりだとか色々機能はありますが、とりあえずこの辺りだけ覚えておけば実用に供すると思います。
subprocessを使って外部プログラムを実行する
https://docs.python.jp/3/library/subprocess.html
subprocessには色々な関数が定義されているのでとりあえずいくつか使いそうなものを試してみます。
例としてPythonから別のPythonのプログラムを実行する処理を実装してみます。
subprocess.check_callによる簡易的な外部プログラムの実行
まずtest.pyを用意します。
# -- test.py -- from time import sleep print('child start!') sleep(1) print('child end!')
これをmain.pyから実行してみます。
# -- main.py -- import subprocess print('parent start!') subprocess.check_call(['python','test.py']) print('parent end!')
$ py main.py parent start! child start! child end! parent end!
check_allは子プロセス(test.py)の終了をまってから次の処理へ進みます。
また外部プログラム側で何かしら例外で終了した場合はcheck_callでも例外を投げます。
# -- error.py -- raise Exception('error test!')
# -- main.py -- import subprocess print('parent start!') subprocess.check_call(['python','error.py']) print('parent end!')
$ py main.py parent start! Traceback (most recent call last): File "error.py", line 1, in <module> raise Exception('error test!') Exception: error test! Traceback (most recent call last): File "main.py", line 8, in <module> ps = subprocess.check_call(['python','error.py']) File "F:\Python36\lib\subprocess.py", line 291, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command '['python', 'error.py']' returned non-zero exit status 1.
subprocess.check_outputで実行されたプログラムの標準出力を得る
check_callと違い、こちらは外部プログラムで実行された標準出力を実行側で文字列で取得することができます。
# -- test.py -- from time import sleep print('child start!') sleep(1) print('child end!')
# -- main.py -- import subprocess output = subprocess.check_output(['python','test.py']) print('---') print(output.decode('sjis'))
$ py main.py --- child start! child end!
ちなみにcheck_outputの戻り値はバイナリ文字列になってるのでdecodeで文字列化してから出力してます。
subprocess.runによる外部プログラムの実行
Python3.5以上からはcheck_callやcheck_outputよりも柔軟なrunを使うこともできます。
check_callをrunで置き換えると以下のようになります。
import subprocess print('parent start!') subprocess.run(['python','test.py'], check=True) print('parent end!')
check_outputをrunで置き換えると以下のようになります。
import subprocess output = subprocess.run(['python','test.py'], check=True, stdout=subprocess.PIPE).stdout print(output.decode('sjis'))
他にも色々できるようですが、ここでは割愛。
目的がハッキリしている場合はcheck_callやcheck_outputでも良さそうですね。
subprocess.Popenによる詳細な外部プログラムの実行
通常ではcheck_allやcheck_output(およびrun)などを使えばそれで基本的には問題がでることはありませんが、例えば子プロセスの終了をまたずに何か処理をしたいとかそういうことをしたい場合にはPopenを使います。
# -- test.py -- from time import sleep print('child start!') sleep(1) print('child end!')
# -- main.py -- import subprocess print('parent start!') ps = subprocess.Popen(['python','test.py']) print('parent end!')
$ py main.py parent start! parent end! child start! child end!
このように子プロセスの終了をまたずに「parent end!」が出力されていますね。
with文を利用したファイルの読み書き
例えば以下のようなファイルの読み込み処理があるとします。
fh = open('text.txt','rt') text = fh.read() fh.close()
with文を使うと以下のようになります
with open('text.txt','rt') as fh text = fh.read()
with文を使うとcloseを明示的に呼ぶ必要がなくなります。
with文のスコープを抜けた時点で自動的に呼ばれます。
便利なので基本的にはファイルの入出力では使った方が良いですね。
with文自体の仕様についてはまた今度。
Pythonでのファイル読み書き基礎
入門Python3 8.1
ファイルの読み書きです。
まずはテキストデータの書き込み処理。
openの第二引数にwを指定すると書き込みとなります。tはテキストモードでこれをbにすればバイナリモードのなります。
fh = open('output.txt','wt') fh.write('hogehoge') fh.close()
$ py main.py
これでoutput.txtが作成されます。
# -- output.txt -- hogehoge
次はテキストデータの読み込みです。
openの第二引数にrを指定すると読み込みとなります。
fh = open('output.txt','rt') text = fh.read() fh.close() print(text)
$ py main.py hogehoge
Pythonでsleep
https://docs.python.jp/3/library/time.html#time.sleep
timeモジュールのsleep関数を使います
from time import sleep print(1) sleep(1) print(2)
$ py main.py 1 1
sleep(1)で1秒スリープする感じです。
float値でもいけるので0.5秒スリープしたりとかもできます。
attrdictを使って辞書をオブジェクト変数としてアクセスできるように変換する
例えばPythonでJSONを読み込むとそれは辞書として変換される
import json data = json.loads('{"a": 1,"b": {"c": 4} }') print(data)
$ py main.py {'a': 1, 'b': {'c': 4}}
辞書なので各要素にアクセスする時は以下のようになる。
import json data = json.loads('{"a": 1,"b": {"c": 4} }') print(data["b"]["c"])
$ py main.py 4
ただいちいち[]つけて書くのがめんどくさい。やっぱdata.b.cとアクセスできた方が楽だし書きやすいよね。
というわけでattrdictというライブラリを使うことでそれが可能となります。
https://pypi.python.org/pypi/attrdict/2.0.0
まずはインストール
$ pip install attrdict
利用例
import json from attrdict import AttrDict data = AttrDict(json.loads('{"a": 1,"b": {"c": 4} }')) print(data.b.c)
$ py main.py 4
便利ですね。