首页 > 后端开发 > Python教程 > 为什么 Python 的 `subprocess.Popen` 和 `readlines()` 会挂起,如何修复它?

为什么 Python 的 `subprocess.Popen` 和 `readlines()` 会挂起,如何修复它?

DDD
发布: 2024-12-03 10:37:10
原创
142 人浏览过

Why Does Python's `subprocess.Popen` with `readlines()` Hang, and How Can I Fix It?

Python子进程readlines()挂起问题

简介

可以实现流式传输文件并逐行打印输出使用各种方法。然而,使用带有 readlines() 的子进程可能会导致挂起问题。

Python 脚本

考虑设计用于流式传输 Ruby 文件“ruby_sleep.rb”的 Python 脚本“main.py”和打印其输出。

import pty
import os
from subprocess import Popen, PIPE, STDOUT

file_path = '/path/to/ruby_sleep.rb'
command = ' '.join(["ruby", file_path])

master, slave = pty.openpty()
proc = Popen(command, bufsize=0, shell=True, stdout=slave, stderr=slave, close_fds=True)     
stdout = os.fdopen(master, 'r', 0)

while proc.poll() is None:
    data = stdout.readline()
    if data != "":
        print(data)
    else:
        break

print("This line is never reached")
登录后复制

问题和观察

执行此脚本按预期流式传输 Ruby 输出,但 readline() 方法无限期挂起,导致“永远无法到达此行”字符串永远不会被打印。

解决方案

已提出各种解决方案来解决此挂起问题:

1.利用 Stdbuf

Stdbuf 可以在非交互模式下启用行缓冲。

from subprocess import Popen, PIPE, STDOUT

proc = Popen(['stdbuf', '-oL', 'ruby', 'ruby_sleep.rb'],
             bufsize=1, stdout=PIPE, stderr=STDOUT, close_fds=True)
for line in iter(proc.stdout.readline, b''):
    print line,
proc.stdout.close()
proc.wait()
登录后复制

2.使用 Pexpect

Pexpect 可用于基于行的控制。

import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)
登录后复制

3.使用 PTY

PTY 允许提供 tty 以在 Ruby 端启用行缓冲。

import os
import pty
from subprocess import Popen, STDOUT

master_fd, slave_fd = pty.openpty()
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
while 1:
    try:
        data = os.read(master_fd, 512)
    except OSError as e:
        if e.errno != errno.EIO:
            raise
        break # EIO means EOF on some systems
    else:
        if not data: # EOF
            break
        print('got ' + repr(data))
finally:
    os.close(master_fd)
    if proc.poll() is None:
        proc.kill()
    proc.wait()
    print("This is reached!")
登录后复制

以上是为什么 Python 的 `subprocess.Popen` 和 `readlines()` 会挂起,如何修复它?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板