Python3 関数オブジェクトを関数に渡せるのを生かして、cron用スクリプトの出力をうまいこと記述する

こんにちは、kisseです。

最近もSQLとPython使って、分析用データセットの定期作成スクリプトとかを書いてます。笑
今日、コード書いているときに、cronスクリプト用の便利な関数を思いついたので、記事にします!



cronスクリプトを書くときの問題

cron用のスクリプトに限らず、複雑な処理を書くときにはどこの処理で時間がかかっているかを出力したいですよね。

なにも考えずに特定の処理に入ったことと、終了したこと、その処理にかかった時間を出力しようとすると、以下のようなコードになると思います。

  
import time

print('Start Process...')
start_time = time.time()

# 何かの処理を実行
someProcess()

end_time = time.time()

# 処理時間をミリ秒で計算
erapsed_time = int((end_time - start_time) * 1000)

print('Finished: {}ms'.format(erapsed_time))

このように書くと、特定の処理に入ったことと、その処理が終わるまでにかかった時間などを出力することができます。
この辺までなら、”Python 処理時間計測”とかでググってもらえると出てくると思います。

しかし、このように計測したい処理が複数存在する場合はどうでしょうか。
このように記述した場合は、1処理に対して5行ほど文字列出力用のコードを記載しなければなりません。

しかも処理の両側にそのようなコードが存在するので、単純な関数ではこれを効率化することは難しいです。



Pythonでは、関数に関数を渡せる

ところで、Pythonでは関数の引数に関数を渡すことができます。
これにより、以下のような関数が考えられます。

import time

def cronUtil(func):
  print('Start process')
  start_time = time.time()

  # ここで所望の処理を実行
  func()

  end_time = time.time()
  erapsed_time = int((end_time - start_time) * 1000)
  print('Finished: {}'.format(erapsed_time))

def someFunc():
  # 処理を記述
  print('Year!')
  pass

if __name__ = '__main__':
  cronUtil(someFunc())

こんな感じで記述すると文字列出力処理を1回しか書かずに済みますね!

ところで、処理関数に引数をとれるようにするには?

上記例では、関数に引数がありませんでしたが引数をとれるようにするにはどうするべきでしょうか??

解決策の一つとして、cronUtil()にキーワード引数で渡した関数の引数を渡すことが挙げられます。
処理関数への引数をリストでcronUtil()に渡し、内部で展開して処理関数に渡すことにしましょう。
また、ついでに処理に入る前に表示する文字列も変更できるようにしときましょう。

import time

def cronUtil(func, arg_list=[], message='Start Process'):
  # キーワード引数でmessageを指定したらここで出力
  print(message)  
  start_time = time.time()

  # *をつけてキーワード引数arg_listを展開して渡す。  
  # 引数を取らない関数には、空のリストを展開すると何も渡さないのと同じ意味になる
  func(*arg_list)

  end_time = time.time()
  erapsed_time = int((end_time - start_time) * 1000)
  print('Finished: {}'.format(erapsed_time))

def add(a, b):
  return a + b

if __name__ == '__main__':
  # キーワード引数を指定してあげる
  ret = cronUtil(add, arg_list=[2, 3], message='Yeah!!!')
  print(ret)

# >>> Yeah!!!
# >>> Finished: 0ms
# >>> 5

これで随分単純に、処理前後で文字列の出力ができるようになりました!!!



おわり

もし、cronスクリプトをPythonで書くようなことがあれば、これをカスタマイズしてみてください。
Pythonは関数オブジェクトを関数に渡せるので、メインの処理の両側にテンプレート的な処理を加えることができます!

最後まで読んでいただきありがとうございます!

あわせて読みたい