首页 > 解决方案 > 在工作进程中运行外部命令并将输出捕获到单个文件

问题描述

这是我在工作进程中调用外部命令并将命令的所有输出附加到单个文件的幼稚方法。这是一个示例代码。

from concurrent.futures import ProcessPoolExecutor
from functools import partial
import multiprocessing
import subprocess

def worker_process_write_output(fh, lock, mylist):
    output = subprocess.run("dir /b", shell=True, stdout=subprocess.PIPE, universal_newlines=True).stdout
    with lock:  # Need lock to prevent multiple processes writing to the file simultenously
        fh.write(mylist)
        fh.writelines(output)    

if __name__ == '__main__':
    with open("outfile.txt", "a") as fh: # I am opening file in main process to avoid the overhead of opening & closing the file multiple times in each worker process
        mylist = [1, 2, 3, 4]
        with ProcessPoolExecutor() as executor:
            lock = multiprocessing.Manager().Lock()
            executor.map(partial(worker_process_write_output, fh, lock), mylist)

此代码在运行时挂起。有哪些错误和更正?我猜其中一些是 1. 无法将文件句柄传递给工作进程。需要在工作进程中打开和关闭文件。不确定原因 2. 不能在工作进程中使用 subprocess.run,需要使用 os.popen("dir /b").read() 或其他 3. 不确定是否需要锁定,如果需要是这是正确的锁吗?

标签: python-3.xpython-multiprocessing

解决方案


文件上下文可以在进程之间传递,所以我不确定你的代码为什么在文件处理程序中死锁。话虽如此,我假设您在run()函数中做了很多工作,因此每个进程打开/关闭文件一次的开销应该不会很大。如果要做的工作不多,那么多处理可能不是开始的最佳选择,因为它涉及严重的开销。

此外,fh.write(mylist)引发 a TypeError: write() argument must be str, not int,因此我们需要使用 进行转换fh.write(str(mylist))

这是解决方法:

import multiprocessing
import subprocess
from concurrent.futures import ProcessPoolExecutor
from functools import partial

def worker_process_write_output(lock, mylist):
    output = subprocess.run("dir /b", shell=True, stdout=subprocess.PIPE,
                            universal_newlines=True).stdout

    with lock:
        with open("outfile.txt", "a") as fh:
            fh.write(str(mylist))
            fh.writelines(output)


if __name__ == '__main__':
    mylist = [1, 2, 3, 4]

    with ProcessPoolExecutor() as executor:
        lock = multiprocessing.Manager().Lock()
        executor.map(partial(worker_process_write_output, lock), mylist)

推荐阅读