Non-blocking read on a subprocess.PIPE in python
(更新)
上のリンクに書いてあるソースにコメントを加え、結果を利用する main 関数を追加。
#!/usr/bin/env python
# -*- coding: sjis -*-
import os
import sys
from subprocess import Popen, PIPE
import threading
import time
try:
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty # python 3.x
# posix モジュールはオペレーティングシステムの機能のうち、C 言語標準 および POSIX 標準 (Unix インタフェースをほんの少し隠蔽した) で標準化されている機能に対するアクセス機構を提供する
# 非 Unix オペレーティングシステムでは posix モジュール を使うことはできない→要するに Unix 系か Windows かを判定している
ON_POSIX = 'posix' in sys.builtin_module_names
def enqueue_output(out, queue):
# iter は第2引数があると、1番目の関数の返り値と2番目の返り値が一致した際に iteration が終わる
for line in iter(out.readline, b''):
queue.put(line.rstrip())
out.close()
print 'enqueue_output finished'
if __name__=='__main__':
argv = sys.argv
argc = len(argv)
if argc != 3:
sys.exit(1)
if not argv[2].isdigit():
sys.exit(1)
keyword = argv[1]
time_limit = int(argv[2])
print 'Keyword : %s' % keyword
print 'Time limit : %d' % time_limit
# stdout=PIPE : 新しいパイプが子プロセスに向けて作られる
# bufsize = 1 : 行毎にバッファ
# close_fds : Unix 系 の場合、 true にすると子プロセス実行前に 0, 1, 2 以外のファイルディスクリプタが閉じられる。
# Windowsの場合、 true にすると子プロセスにハンドルが継承されない。 Windows の場合は close_fds を true にしながら、 stdin, stdout, stderr を利用して標準ハンドルをリダイレクトすることはできない
p = Popen(['python','outputter.py'], stdout=PIPE, bufsize=1, close_fds=ON_POSIX)
q = Queue()
t = threading.Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # プログラムの終了と同時に終了する
t.start()
startTime = time.time()
keyword_found = False
while True:
if time.time() - startTime > time_limit:
print 'Time out. Keyword %s not found...' % keyword
keyword_found = False
break
try:
line = q.get_nowait() # タイムアウト無しで取得。何もなければ Empty 例外を出す
except Empty:
continue
# print('no output yet')
else: # got line
if line == keyword:
print 'Keyword %s found' % keyword
keyword_found = True
break
else:
print line
try:
p.kill()
except OSError:
pass
if keyword_found:
print 'Success'
else:
print 'False'
0 件のコメント:
コメントを投稿