使用`subprocess.Popen`实时在Python中运行Python脚本 [英] Run Python script within Python by using `subprocess.Popen` in real time

查看:68
本文介绍了使用`subprocess.Popen`实时在Python中运行Python脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从 Python 脚本运行 Python 脚本(或任何可执行文件,以这种方式)并实时获取输出.我遵循了很多教程,我当前的代码如下所示:

I want to run a Python script (or any executable, for that manner) from a python script and get the output in real time. I have followed many tutorials, and my current code looks like this:

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()

为了清楚起见,第一位只是创建将要运行的文件.

The first bit just creates the file that will be run, for clarity's sake.

这段代码有两个问题:

  • 它不会实时给出输出.它一直等到该过程完成.

  • It does not give the output in real time. It waits untill the process has finished.

一旦进程完成,它不会终止循环.

It does not terminate the loop once the process has finished.

非常欢迎任何帮助.

感谢@JohnAnderson 修复了第一个问题:用 if output == b 替换 if output == '' and process.poll() is not None:'' 并且 process.poll() 不是 None:

Thanks to @JohnAnderson for the fix to the first problem: replacing if output == '' and process.poll() is not None: with if output == b'' and process.poll() is not None:

推荐答案

昨晚我开始使用管道来做这个:

Last night I've set out to do this using a pipe:

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,您可以免费获得大部分内容,我以这个结束,这似乎工作正常(根据需要调用 read 多次以保持清空管道),并假设过程完成,您不必担心轮询它和/或确保管道的写端关闭以正确检测 EOF 并退出循环:

Forcing buffering out of the picture and reading one character at the time (to make sure we do not block writes from the process having filled a buffer), closing the writing end when process finishes to make sure read catches the EOF correctly. Having looked at the subprocess though that turned out to be a bit of an overkill. With PIPE you get most of that for free and I ended with this which seems to work fine (call read as many times as necessary to keep emptying the pipe) with just this and assuming the process finished, you do not have to worry about polling it and/or making sure the write end of the pipe is closed to correctly detect EOF and get out of the loop:

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()

这有点不太实时",因为它基本上是行缓冲的.

This is a bit less "real-time" as it is basically line buffered.

注意:我已将 -u 添加到您的 Python 调用中,因为您还需要确保被调用进程的缓冲不会妨碍.

Note: I've added -u to you Python call, as you need to also make sure your called process' buffering does not get in the way.

这篇关于使用`subprocess.Popen`实时在Python中运行Python脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆