プロセス系のPythonスクリプトを書いていると、あるプログラムが指定時間以上経過したら即座にプログラムをエラーとみなして終了したい、という処理をしたい時がある。
例えばSeleniumとかでWebチェックをする時、ほっておくといつまでたっても返事がかえってこない。そのため時間制限をもうけて、時間以内は正常、それ以外は異常など処理したい時など。
(
お弁当宅配サイトのマイ食の自動テストサービスを作っているときにこの必要性があった)
ここではフォークして、今の仕事を子供プロセスに任せる。親プロセスは子プロセスを指定時間までまち、指定時間経過後もまだ子供プロセスが生きていたら殺す。というプログラムの例を載せる。
signal, os, sysなどを使う。
本当はThreadingを使ってSignalをやりとりでいいじゃないか!という人もいるかもしれないけれど今回はそうしなかった。感覚的にThreadingでSignalをやり取りするのはなんかマズイ気がするが…。
とにかく今回はForkで。。
import time, os, sys, signal
def mysleep( secs ): time.sleep( secs ) def doit( limit_waiting_time, function, **args ): child_id = os.fork() if child_id != 0: # Parent process # Waiting for child process to do some works time.sleep( limit_waiting_time ) # Seach child process whther the process is workinng. commands = os.popen( 'ps aux | grep %d | grep -v grep' % child_id ) lines = commands.readlines() # There is no line or Zonbi process in the line, then the child was dead. ( OK ) if len( lines ) == 0 or 'Z+' in lines[ 0 ].strip(): CAN_KILLED=True else: # The child process is still working( not killed, not good ) os.kill( child_id, signal.SIGKILL ) # kill it. CAN_KILLED=False
if CAN_KILLED: return True else: return False else: # !! Child process !! function( **args ) # doit something as child. sys.exit() # <= not to write os._exit def main(): print doit( 3, mysleep, secs = 5.0 )
if __name__ == '__main__': main()
|
関数のmysleepはサンプルのために作った適当な関数。この部分を独自の関数にすればいい。
doitがメインの関数となっている。(名前に問題あるかもしれないけど、今はこれでいいかなと)
株式会社OctOpt
コンピューターサイエンス会社OctOptの技術公式ブログ等々力 康弘
@rocky_house