Python 确保线程上次执行工作
最后,我能够生成多个子进程,并使用线程将它们的stdout实时导入python 我有一个dict列表,其中包含生成子进程和从管道读取的线程所需的所有数据结构。我想要运行的特定程序需要几个小时才能完成,因此我可以接受这样一个事实,即标准输出仅每4096字节刷新一次 下面是一些精简的代码:Python 确保线程上次执行工作,python,multithreading,subprocess,Python,Multithreading,Subprocess,最后,我能够生成多个子进程,并使用线程将它们的stdout实时导入python 我有一个dict列表,其中包含生成子进程和从管道读取的线程所需的所有数据结构。我想要运行的特定程序需要几个小时才能完成,因此我可以接受这样一个事实,即标准输出仅每4096字节刷新一次 下面是一些精简的代码: from time import sleep import subprocess from threading import Thread from Queue import Queue, Empty def
from time import sleep
import subprocess
from threading import Thread
from Queue import Queue, Empty
def enqueue_output(out, queue):
for line in iter(out.readline, b''):
queue.put(line)
out.close()
def queue_get_all(queue):
items = []
while True:
try:
items.append(queue.get_nowait())
except Empty, e:
break
return items
worklist=[
{
'cmd' :r'command 1',
'pid' :None,
'queue' :None,
'thread' :None
},{
'cmd' :r'command 2',
'pid' :None,
'queue' :None,
'thread' :None
},{
'cmd' :r'command 3',
'pid' :None,
'queue' :None,
'thread' :None
}
]
for work in worklist:
work['pid'] = subprocess.Popen(work['cmd'], stdout=subprocess.PIPE, stderr=subprocess.PIPE,bufsize=0)
work['queue'] = Queue()
work['thread'] = Thread(target=enqueue_output, args=(work['pid'].stdout, work['queue']))
work['thread'].daemon = True
work['thread'].start()
finalflush = False
while True:
for work in worklist:
lines = queue_get_all(work['queue'])
for line in lines:
print line
if all(item['pid'].poll() is not None for item in worklist):
if finalflush == False:
sleep(10)
finalflush = True
continue
else:
break
for work in worklist:
work['pid'].wait()
因此,我面临的问题是,一旦所有进程都完成,因此all(工作列表中的项['pid'].poll()不是None)
是真的。在stdout管道中仍然可能有一些我的线程尚未读取的信息。
我的破解方法是在所有子进程完成后等待10秒,然后最后运行一次循环。这可能永远不会导致任何问题,但我真的不喜欢这种方式,我想知道是否可以进行真正的修复,以便在子进程完成后,我的线程被迫再次读取 你就不能
join()
每个线程吗?怎么会这样?即使子进程已经完成,线程也不会继续它的工作(例如,从我管道中的标准输出读取)。对,线程将继续工作,直到它从out.readline
获得EOF,这是您想要的,不是吗?只有在十秒钟睡眠后调用work['pid'].wait()
时,才会刷新标准输出缓冲区吗?如果你只做睡眠
,它能工作吗?或者只需执行等待
?如果调用work['pid'].stdout.flush()
,会怎么样?我没有意识到我的stdout会生成EOF。标准输出缓冲区每4096字节刷新一次,并在程序退出时刷新一次。在它上面调用stdout.flush()没有什么区别,因为windows会缓冲它。。。我的等待只是为了让线程能够完成阅读。但如果生成EOF,我确实可以使用.join()`