Edited at

python-fireへの雑な理解と素振りメモ

More than 1 year has passed since last update.

Python-fireの記事とかがはてぶとかでちょこちょこ上がったので、素振りして見たメモ。


動作確認してた環境


  • Macbook Pro 13inch Early 2015

  • Python 3.6.0 from pyenv


自分でREADMEを読んでみただけの時の感想

argparseでよくね?


実際に比較する

単純な「受け付けた引数2個を足した結果をかえす」サブコマンドaddを持つCLIについて考えてみました。

calc-1.pypython-fireに任せたもの、calc-2.pyはそれをargparseに置き換え直したものです。


calc-1.py

import fire

class Calcurator(object):
def add(self, first, second):
return int(first) + int(second)

if __name__ == '__main__':
fire.Fire(Calcurator)



calc-2.py

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('mode')
parser.add_argument('first')
parser.add_argument('second')

class Calcurator(object):
def add(self, first, second):
return int(first) + int(second)

if __name__ == '__main__':
args = parser.parse_args()
cli = Calcurator()
print(getattr(cli, args.mode)(args.first, args.second))


ものすごく、可読性がよくなる気がする。

ちょこちょこCLIな処理を書くと、コードの結構な割合をargument parserの部分が占めるので、これがなくなると割とありがたいかもしれない。


ヘルプ表示的なもの

(subcommand) -- --hepで引数情報とかを取ってくれるらしい。


calc-1.py

$ python calc-1.py add  -- --help

Type: method
String form: <bound method Calcurator.add of <__main__.Calcurator object at 0x1036f8fd0>>
File: ~/Dropbox (nijibox)/Applications/act/calc-1.py
Line: 5

Usage: calc-1.py add FIRST SECOND
calc-1.py add --first FIRST --second SECOND



calc-2.py

$ python calc-2.py -h

usage: calc-2.py [-h] mode first second

positional arguments:
mode
first
second

optional arguments:
-h, --help show this help message and exit


ファイル情報とかはちょっと邪魔だけど、Usageとしての役割は果たしている模様。


処理時間を比較する

何も考えずに呼び出しをすると、あからさまにcalc-1.pyの方が処理が遅くなる。

$ time python calc-1.py add 12345 67890

80235
python calc-1.py add 12345 67890 0.60s user 0.29s system 30% cpu 2.945 total

$ time python calc-2.py add 12345 67890
80235
python calc-2.py add 12345 67890 0.07s user 0.07s system 77% cpu 0.179 total

単純に一回だけ比較するとこんな感じ。0.5secぐらいの差がある模様。

で、こんなループをさせてみた。


loop.py

import sys

import subprocess

script = sys.argv[1]
count = int(sys.argv[2])

for _ in range(count):
proc = subprocess.Popen('python {} add 12345 67890'.format(script).split(), stdout=None)
proc.communicate()



loop.py

$ time python loop.py calc-1.py 10 > /dev/null

python loop.py calc-1.py 10 > /dev/null 4.29s user 1.20s system 97% cpu 5.651 total

$ time python loop.py calc-2.py 10 > /dev/null
python loop.py calc-2.py 10 > /dev/null 0.40s user 0.17s system 93% cpu 0.614 total

$ time python loop.py calc-1.py 100 > /dev/null
python loop.py calc-1.py 100 > /dev/null 45.53s user 12.45s system 88% cpu 1:05.32 total

$ time python loop.py calc-2.py 100 > /dev/null
python loop.py calc-2.py 100 > /dev/null 3.39s user 1.06s system 94% cpu 4.731 total


雑に回数重ねてみたけど、平均するとやっぱり0.4〜0.5秒ぐらいの時間が余計にかかっている感じ。

サンプルコードはメイン処理が余りにもシンプルな処理なことを考慮すると、実運用だと誤差になってくるケースは十分ありそう。


軽く検証した後の感想

python-fireいいな