更好地多线程使用Python subprocess.Popen&communicate()?

2024-05-20 01:33:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我在运行Python 2.6的Linux机器上运行多个命令,这可能需要一些时间。

因此,我使用subprocess.Popen类和process.communicate()方法并行执行多个命令组,并在执行后立即捕获输出。

def run_commands(commands, print_lock):
    # this part runs in parallel.
    outputs = []
    for command in commands:
        proc = subprocess.Popen(shlex.split(command), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
        output, unused_err = proc.communicate()  # buffers the output
        retcode = proc.poll()                    # ensures subprocess termination
        outputs.append(output)
    with print_lock: # print them at once (synchronized)
        for output in outputs:
            for line in output.splitlines():
                print(line)

在别的地方,它的名字是这样的:

processes = []
print_lock = Lock()
for ...:
    commands = ...  # a group of commands is generated, which takes some time.
    processes.append(Thread(target=run_commands, args=(commands, print_lock)))
    processes[-1].start()
for p in processes: p.join()
print('done.')

预期的结果是,一组命令的每个输出在并行执行时同时显示。

但是从第二个输出组(当然,成为第二个的线程由于调度的不确定性而改变)开始,它开始打印,没有换行符,并且添加的空格数与前一行中打印的字符数相同,并且输入回声被关闭——终端状态是“混乱”或“崩溃”。(如果我发出resetshell命令,它将恢复正常。)

起初,我试图从'\r'的处理中找到原因,但这不是原因。正如您在我的代码中所看到的,我使用splitlines()正确地处理了它,并且通过对输出应用repr()函数确认了这一点。

我认为原因是在stdout/stderr的Popencommunicate()中同时使用管道。我在Python2.7中尝试了check_output快捷方法,但没有成功。当然,如果我序列化所有命令执行和打印,则不会出现上述问题。

有没有更好的方法来并行处理Popencommunicate()


Tags: 方法in命令lockforoutput原因proc
3条回答

我不确定run_命令实际需要做什么,但它似乎只是对子进程进行轮询,忽略返回代码并继续循环。当您到达打印输出的部分时,您如何知道子流程已经完成?

在您的示例代码中,我注意到您使用了:

for line in output.splitlines(): 

部分解决“使用

for line in output.splitlines(True): 

会有帮助的。

一个最终的结果灵感来自J.F.Sebastian的评论。

http://bitbucket.org/daybreaker/kaist-cs443/src/247f9ecf3cee/tools/manage.py

这似乎是一个Python bug。

相关问题 更多 >