我需要运行一个程序并将其输出收集到stdout。这个程序(socat)需要在python脚本的持续时间内在后台运行。一旦它运行,Socat就会处于dameon模式,但首先它会向stdout输出一些我需要用于其余脚本的行。
命令:socat -d -d PTY: PTY:
输出:
2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/1
2011/03/23 21:12:35 socat[7476] N PTY is /dev/pts/2
2011/03/23 21:12:35 socat[7476] N starting data transfer loop with FDs [3,3] and [5,5]
...
我基本上想在程序开始时运行它并让它一直运行直到脚本终止,但我需要将两个/ dev / pts / X名称读入python。
谁能告诉我怎么做?
我想出了这个只是挂起的,我猜是因为它阻止子进程终止。
#!/usr/bin/python
from subprocess import Popen, PIPE, STDOUT
cmd = 'socat -d -d PTY: PTY: &'
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
output = p.stdout.read()
# Process the output
print(output)
感谢您的帮助
编辑:似乎它可能写入stderr,但剧本仍然只是在有和没有&甚至从stderr读到。答案 0 :(得分:22)
#!/usr/bin/python
from subprocess import Popen, PIPE, STDOUT
import pty
import os
cmd = 'socat -d -d PTY: PTY:'
master, slave = pty.openpty()
p = Popen(cmd, shell=True, stdin=PIPE, stdout=slave, stderr=slave, close_fds=True)
stdout = os.fdopen(master)
print stdout.readline()
print stdout.readline()
您的版本有两个问题。首先,你不带参数调用read,这意味着它将尝试读取所有内容。但是,由于socat没有终止,它从未决定它已经阅读了所有内容。通过使用readline,python只读取直到找到换行符。从我对你所需要的问题的理解来看。
第二个问题是C标准库将缓冲管道上的输出。我们通过使用openpty()函数创建一个pty并将其传递给子进程的stdout和stderr来解决这个问题。我们使用fdopen将该文件描述符转换为常规python对象,然后我们摆脱了缓冲。
我不知道你在使用socat做了什么,但我想知道是否可以用pty模块代替它。你正在将一个pty复制到另一个pty,而openpty正在创建一对ptys。也许你可以直接使用它们?
答案 1 :(得分:1)
子进程可能永远不会关闭stdout,因此read()
调用将永远等待。更糟糕的是,当它发现它是管道而不是控制台时,它可能会缓冲其输出(标准C库会自动执行此操作,因此这不是应用程序编写得如何巧妙的功能)。如果是这样,可能唯一的选择是使用期望式库,例如Pexpect。
答案 2 :(得分:0)
如果你为stdout和stderr提供管道,我认为子进程将阻塞等待管道被读取。我想,.read()应该读到EOF。在他们之间,这两个问题大量陷入僵局。
但是,我认为既然.read()会读到EOF,即使没有stderr管也会阻塞。
我想你想把阅读贴在一个帖子里。