python:非阻塞子进程,检查标准输出

2022-01-18 00:00:00 python subprocess popen stdout nonblocking

问题描述

好的,我要解决的问题是:

Ok so the problem I'm trying to solve is this:

我需要运行一个设置了一些标志的程序,检查其进度并向服务器报告.所以我需要我的脚本来避免在程序执行时阻塞,但我还需要能够读取输出.不幸的是,我认为 Popen 提供的任何方法都不会在不阻塞的情况下读取输出.我尝试了以下,这有点hack-y(我们是否允许从两个不同的对象读取和写入同一个文件?)

I need to run a program with some flags set, check on its progress and report back to a server. So I need my script to avoid blocking while the program executes, but I also need to be able to read the output. Unfortunately, I don't think any of the methods available from Popen will read the output without blocking. I tried the following, which is a bit hack-y (are we allowed to read and write to the same file from two different objects?)

import time
import subprocess
from subprocess import *
with open("stdout.txt", "wb") as outf:
    with open("stderr.txt", "wb") as errf:
        command = ['Path\To\Program.exe', 'para', 'met', 'ers']
        p = subprocess.Popen(command, stdout=outf, stderr=errf)
        isdone = False
        while not isdone :
            with open("stdout.txt", "rb") as readoutf: #this feels wrong
                for line in readoutf:
                    print(line)
            print("waiting...\r\n")
            if(p.poll() != None) :
                done = True
            time.sleep(1)
        output = p.communicate()[0]    
        print(output)

不幸的是,Popen 似乎直到命令终止后才写入我的文件.

Unfortunately, Popen doesn't seem to write to my file until after the command terminates.

有人知道这样做的方法吗?我并不热衷于使用 python,但我确实需要在同一个脚本中向服务器发送 POST 请求,因此 python 似乎比 shell 脚本更容易.

Does anyone know of a way to do this? I'm not dedicated to using python, but I do need to send POST requests to a server in the same script, so python seemed like an easier choice than, say, shell scripting.

谢谢!会


解决方案

基本上你有3个选择:

  1. 使用threading在另一个线程中读取而不阻塞主线程.
  2. select在标准输出上,标准错误而不是 communicate.这样您就可以在数据可用时进行读取,避免阻塞.
  3. 让一个库来解决这个问题,twisted是一个显而易见的选择.
  1. Use threading to read in another thread without blocking the main thread.
  2. select on stdout, stderr instead of communicate. This way you can read just when data is available and avoid blocking.
  3. Let a library solve this, twisted is a obvious choice.

相关文章