通过实时使用`subprocess.Popen`在Python中运行Python脚本

问题描述 投票:2回答:1

我想从python脚本运行Python脚本(或任何可执行文件),并实时获取输出。我已经遵循了许多教程,我的当前代码如下所示:

import subprocess
with open("test2", "w") as f:
    f.write("""import time
print('start')
time.sleep(5)
print('done')""")

process = subprocess.Popen(['python3', "test2"], stdout=subprocess.PIPE)
while True:
        output = process.stdout.readline()
        if output == '' and process.poll() is not None:
            break
        if output:
            print(output.strip())
        rc = process.poll()

为清楚起见,第一位只创建将运行的文件。

这个代码有两个问题:

  • 它不会实时提供输出。它一直等到过程结束。
  • 一旦进程完成,它不会终止循环。

任何帮助都会非常受欢迎。

编辑:感谢@JohnAnderson解决第一个问题:用if output == '' and process.poll() is not None:替换if output == b'' and process.poll() is not None:

python python-3.x subprocess
1个回答
1
投票

昨晚我打算用管子做这件事:

import os
import subprocess

with open("test2", "w") as f:
    f.write("""import time
print('start')
time.sleep(2)
print('done')""")

(readend, writeend) = os.pipe()

p = subprocess.Popen(['python3', '-u', 'test2'], stdout=writeend, bufsize=0)
still_open = True
output = ""
output_buf = os.read(readend, 1).decode()
while output_buf:
    print(output_buf, end="")
    output += output_buf
    if still_open and p.poll() is not None:
        os.close(writeend)
        still_open = False
    output_buf = os.read(readend, 1).decode()

强制缓冲图片并一次读取一个字符(以确保我们不会阻止来自填充缓冲区的进程的写入),在进程完成时关闭写入结束以确保读取正确捕获EOF。看了subprocess虽然结果有点矫枉过正。使用PIPE,您可以免费获得大部分内容,我最终使用了这个似乎工作正常(尽可能多次调用读取以保持排空管道)并且假设过程完成,您不必担心轮询它和/或确保关闭管道的写入端以正确检测EOF并退出循环:

p = subprocess.Popen(['python3', '-u', 'test2'],
                     stdout=subprocess.PIPE, bufsize=1,
                     universal_newlines=True)
output = ""
output_buf = p.stdout.readline()
while output_buf:
    print(output_buf, end="")
    output += output_buf
    output_buf = p.stdout.readline()

这有点“实时”,因为它基本上是行缓冲的。

注意:我已经在你的Python调用中添加了-u,因为你还需要确保你的被调用进程的缓冲不会妨碍你。

© www.soinside.com 2019 - 2024. All rights reserved.