簡體   English   中英

在 Python 中對子進程 PIPE 進行非阻塞讀取,一次一個字節

[英]Non-blocking read on subprocess PIPE in Python, one byte at a time

我在這個問題的代碼上實現了一個變體:

Python 中 subprocess.PIPE 的非阻塞讀取

要嘗試從這個虛擬程序test.py實時讀取輸出:

import time, sys

print "Hello there"
for i in range(100):
    time.sleep(0.1)
    sys.stdout.write("\r%d"%i)
    sys.stdout.flush()
print
print "Go now or I shall taunt you once again!"

另一個問題的變化是調用程序必須逐個字符而不是逐行讀取,因為虛擬程序test.py使用\\r在一行上輸出進度指示。 所以這里是:

import sys,time
from subprocess import PIPE, Popen
from threading  import Thread

try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty  # Python 3.x

ON_POSIX = 'posix' in sys.builtin_module_names

def enqueue_output(out, queue):
    while True:
        buffersize = 1
        data = out.read(buffersize)
        if not data:
            break
        queue.put(data)
    out.close()

p = Popen(sys.executable + " test.py", stdout=PIPE, bufsize=1, close_fds=ON_POSIX)
q = Queue()
t = Thread(target=enqueue_output, args=(p.stdout, q))
t.daemon = True # Thread dies with the program
t.start()

while True:
    p.poll()
    if p.returncode:
        break
    # Read line without blocking
    try:
        char = q.get_nowait()
        time.sleep(0.1)
    except Empty:
        pass
    else: # Got line
        sys.stdout.write(char)
        sys.stdout.flush()

print "left loop"
sys.exit(0)

這有兩個問題

  • 它永遠不會退出 - p.returncode永遠不會返回值,並且不會留下循環。 我該如何解決?
  • 真的很慢! 有沒有辦法在不增加buffersize情況下提高效率?

正如@Markku K. 指出的那樣,您應該使用bufsize=0讀取一個字節。

您的代碼不需要非阻塞讀取。 你可以簡化它:

import sys
from functools import partial
from subprocess import Popen, PIPE

p = Popen([sys.executable, "test.py"], stdout=PIPE, bufsize=0)
for b in iter(partial(p.stdout.read, 1), b""):
    print b # it should print as soon as `sys.stdout.flush()` is called
            # in the test.py
p.stdout.close()
p.wait()

注意:一次讀取 1 個字節是非常低效的。

此外,通常可能存在塊緩沖問題,有時可以使用pexpectpty模塊unbufferstdbufscript命令行實用程序來解決

對於 Python 進程,您可以使用-u標志來強制對 stdin、stdout、stderr 流進行非緩沖(二進制層)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM