使用子进程时,执行非阻塞读取以避免停止父进程至关重要在等待子进程的输出时。使用 subprocess.Popen 时会出现此问题,其中如果没有可用数据,则 readline() 会阻塞。
传统阻塞方法
通常,开发人员使用以下代码来读取从子进程的标准输出:
p = subprocess.Popen('myprogram.exe', stdout = subprocess.PIPE) output_str = p.stdout.readline()
但是,如果没有可用数据。
非阻塞解决方案
可靠的跨平台解决方案涉及利用 Queue.get_nowait(),如下面的代码所示:
import sys from subprocess import PIPE, Popen from threading import Thread try: from queue import Queue, Empty except ImportError: from Queue import Queue, Empty # python 2.x ON_POSIX = 'posix' in sys.builtin_module_names def enqueue_output(out, queue): for line in iter(out.readline, b''): queue.put(line) out.close() p = Popen(['myprogram.exe'], 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() # ... do other things here # read line without blocking try: line = q.get_nowait() # or q.get(timeout=.1) except Empty: print('no output yet') else: # got line # ... do something with line
此方法使用单独的线程将输出行排入队列。然后主线程可以使用 get_nowait() 检查队列是否包含数据而不会阻塞。这种便携式解决方案允许跨各种操作系统对子进程输出进行非阻塞读取。
以上是如何从子进程 PIPE 执行非阻塞读取?的详细内容。更多信息请关注PHP中文网其他相关文章!