当前位置: 首页 > 面试题库 >

Python子进程readlines()挂起

陆雅志
2023-03-14
问题内容

我尝试完成的任务是流式处理ruby文件并打印输出。(注意:我不想一次打印出所有内容)

main.py

from subprocess import Popen, PIPE, STDOUT

import pty
import os

file_path = '/Users/luciano/Desktop/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 is never reached!")
ruby_sleep.rb

puts “hello”

sleep 2

puts "goodbye!"

问题

流文件工作正常。打招呼/再见输出将延迟2秒打印。就像脚本应该工作一样。问题是readline()最终挂起并且永不退出。我从来没有达到最后的打印。

我知道这里有很多类似的问题,但是这些都不是让我解决问题的方法。我并不是整个子流程中的人,所以请给我一个更实际的/具体的答案。

问候

编辑

修复意外的代码。(与实际错误无关)


问题答案:

我假设你pty是出于Q中概述的原因而使用的:为什么不仅仅使用管道(popen())?(到目前为止,所有其他答案都将忽略你的“注意:我不想一次打印所有内容”)。

pty仅在docs中说过是Linux :

由于伪终端处理高度依赖平台,因此有代码仅适用于Linux。(Linux代码应该可以在其他平台上运行,但尚未经过测试。)

目前尚不清楚它在其他操作系统上的运行情况。

你可以尝试pexpect:

import sys
import pexpect

pexpect.run("ruby ruby_sleep.rb", logfile=sys.stdout)

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

或者pty基于@Antti Haapala的答案从stdlib 使用:

#!/usr/bin/env python
import errno
import os
import pty
from subprocess import Popen, STDOUT

master_fd, slave_fd = pty.openpty()  # provide tty to enable
                                     # line-buffering on ruby's side
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdin=slave_fd, stdout=slave_fd, stderr=STDOUT, close_fds=True)
os.close(slave_fd)
try:
    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!")

这三个代码示例都立即打印“ hello”(在看到第一个EOL时)。

此处保留旧的更复杂的代码示例,因为可能会在SO的其他帖子中进行引用和讨论

或者使用pty基于@Antti Haapala的答案:

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

master_fd, slave_fd = pty.openpty()  # provide tty to enable
                                     # line-buffering on ruby's side
proc = Popen(['ruby', 'ruby_sleep.rb'],
             stdout=slave_fd, stderr=STDOUT, close_fds=True)
timeout = .04 # seconds
while 1:
    ready, _, _ = select.select([master_fd], [], [], timeout)
    if ready:
        data = os.read(master_fd, 512)
        if not data:
            break
        print("got " + repr(data))
    elif proc.poll() is not None: # select timeout
        assert not select.select([master_fd], [], [], 0)[0] # detect race condition
        break # proc exited
os.close(slave_fd) # can't do it sooner: it leads to errno.EIO error
os.close(master_fd)
proc.wait()

print("This is reached!")


 类似资料:
  • 问题内容: Python版本:2.6.7 我在for循环中有以下subprocess.call,该循环被执行18次,但是,该过程始终挂在第19个循环上: 控制台输出如下所示: 由于我对python脚本不是很熟悉,所以我只是在徘徊我是否在做错什么…我怀疑某个地方出现了死锁。 会处理这些问题吗? 在什么情况下subprocess.call会挂起任何专家答案?非常感谢 问题答案: 当使用子过程时,我倾向

  • 问题内容: 好的,所以我试图从python脚本运行C程序。目前,我正在使用测试C程序: 为了模拟我将要使用的程序,该程序会不断读取传感器的读数。然后,我尝试”2000”使用python中的子进程从C程序读取输出(在本例中为): 但这不起作用。从使用print语句开始,它运行该行,然后在处等待:,直到我按。 为什么是这样?这正是我所看到的大多数示例作为其代码的内容,但是却没有读取该文件。 编辑: 有

  • 主要内容:Python readline()函数,Python readlines()函数前面章节中讲到,如果想读取用 open() 函数打开的文件中的内容,除了可以使用 read() 函数,还可以使用 readline() 和 readlines() 函数。 和 read() 函数不同,这 2 个函数都以“行”作为读取单位,即每次都读取目标文件中的一行。对于读取以文本格式打开的文件,读取一行很好理解;对于读取以二进制格式打开的文件,它们会以“\n”作为读取一行的标志。 Python

  • 问题内容: 是否有任何参数或选项可为Python的subprocess.Popen方法设置超时? 像这样: ? 问题答案: 我会建议采取看看类中的模块。我用它来实现超时。 首先,创建一个回调: 然后打开过程: 然后创建一个计时器,该计时器将调用回调,并将过程传递给它。 在程序后面的某个位置,您可能需要添加以下行: 否则,python程序将继续运行,直到计时器运行完毕。 编辑:我被告知, 在和条件之

  • 问题内容: 有没有办法在python中“持久”进行子过程调用?我正在调用一个程序,该程序需要一段时间才能加载多次。因此,如果我不关闭程序就可以保持打开状态并与之通信,那将是很好的。 我的python脚本的卡通版本如下所示: 我需要分别处理每个文本,因此将它们全部合并到一个大文本文件中并进行一次处理不是一种选择。 最好,如果有这样的选择 我可以让流程保持开放状态,对此我将非常感激。 问题答案: 您可

  • 问题内容: 我想同时运行许多进程并能够随时输出stdout。我该怎么办?我需要为每个调用运行线程吗? 问题答案: 您可以在一个线程中完成。 假设您有一个脚本可以随机打印行: 而且您想在输出可用后立即收集它,您可以按照@zigg的建议在POSIX系统上 使用: 更具可移植性的解决方案(应在Windows,Linux,OSX上运行)可以为每个进程使用读取器线程,请参阅python中的对子进程的非阻塞读