Я сократил проблему, которую видел в своем приложении, до следующего контрольного примера.В этом коде родительский процесс одновременно порождает 2 (вы можете создать больше) подпроцесса, которые читают большое сообщение от родителя через стандартный ввод данных, спят в течение 5 секунд и что-то записывают обратно.Однако где-то происходит неожиданное ожидание, в результате чего код завершается за 10 секунд вместо ожидаемых 5.
Если вы установите verbose=True
, вы увидите, что запутанный подпроцесс получает большинство сообщений, затеможидание последнего куска из 3 символов --- это не обнаружение, что труба была закрыта.Кроме того, если я просто ничего не буду делать со вторым процессом (doreturn=True
), первый процесс никогда не увидит EOF.
Есть идеи, что происходит?Ниже приведен пример выходных данных.Заранее спасибо.
from subprocess import *
from threading import *
from time import *
from traceback import *
import sys
verbose = False
doreturn = False
msg = (20*4096+3)*'a'
def elapsed(): return '%7.3f' % (time() - start)
if sys.argv[1:]:
start = float(sys.argv[2])
if verbose:
for chunk in iter(lambda: sys.stdin.read(4096), ''):
print >> sys.stderr, '..', time(), sys.argv[1], 'read', len(chunk)
else:
sys.stdin.read()
print >> sys.stderr, elapsed(), '..', sys.argv[1], 'done reading'
sleep(5)
print msg
else:
start = time()
def go(i):
print elapsed(), i, 'starting'
p = Popen(['python','stuckproc.py',str(i), str(start)], stdin=PIPE, stdout=PIPE)
if doreturn and i == 1: return
print elapsed(), i, 'writing'
p.stdin.write(msg)
print elapsed(), i, 'closing'
p.stdin.close()
print elapsed(), i, 'reading'
p.stdout.read()
print elapsed(), i, 'done'
ts = [Thread(target=go, args=(i,)) for i in xrange(2)]
for t in ts: t.start()
for t in ts: t.join()
Пример вывода:
0.001 0 starting
0.003 1 starting
0.005 0 writing
0.016 1 writing
0.093 0 closing
0.093 0 reading
0.094 1 closing
0.094 1 reading
0.098 .. 1 done reading
5.103 1 done
5.108 .. 0 done reading
10.113 0 done
Я использую Python 2.6.5, если это имеет значение.