如何将subprocess.check_call的stdout重定向到函数?

3 投票
2 回答
3140 浏览
提问于 2025-04-16 14:44

调用 subprocess.check_call() 可以指定一个文件对象来接收输出,但在把数据写入文件之前,我想逐行修改这些数据。

目前,我是把输出重定向到一个临时文件(这个临时文件是用 tempfile.TemporaryFile() 创建的)。在 check_call 执行完后,我逐行读取这个临时文件,进行修改,然后写入最终的输出文件。

因为输出的数据量很大,所以单纯在内存中处理是不现实的,我想要边处理边写入最终的输出文件。

有没有人知道怎么做到这一点?

2 个回答

-1

Python是一种鸭子类型的语言,这意味着你可以在把文件对象传给check_call之前,先把它包裹起来。

这个回答里有个例子,展示了如何为write()方法进行包裹,你可以看看。不过,为了更全面,你可能还想把writelines()方法也包裹一下。

2
def check_call_modify(command, modifier_function, output_file)
    p = subprocess.Popen(command, stdout=subprocess.PIPE)
    for line in p.stdout:
        line = modifier_function(line)
        output_file.write(line)    
    p.wait()
    if p.returncode:
        raise subprocess.CalledProcessError(p.returncode, command)
    return p.returncode

要使用这个功能,你需要传递一个函数来修改每一行和文件。下面这个简单的例子会把 ls -l 的结果转换成大写,并保存到 listupper.txt 文件里:

with open('listupper.txt', 'w') as f:
    check_call_modify(['ls', '-l'], operator.methodcaller('upper'), f)

撰写回答