Python如何读取pexpect子进程的输出?

37
child = pexpect.spawn ('/bin/bash')
child.sendline('ls')
print(child.readline())
print child.before, child.after

使用这段代码,我在输出中得到的只有

ls

ls 

但当我的代码是

child = pexpect.spawn('ls')
print(child.readline())
print child.before, child.after

然后它可以工作,但仅适用于前两次打印。我是否使用了错误的发送命令?我尝试了send、write、sendline,但找不到更多。

8个回答

27

在 pexpect 中,beforeafter 属性是在执行 expect 方法后填充的。在这种情况下使用最常见的是等待提示符(这样你就知道前一个命令已经执行完毕)。因此,在您的情况下,代码可能看起来像这样:

child = pexpect.spawn ('/bin/bash')
child.expect("Your bash prompt here")
child.sendline('ls')
#If you are using pxssh you can use this
#child.prompt()
child.expect("Your bash prompt here")
print(child.before)

2
有没有办法在打印“child.before”时忽略您编写的命令?我想我只需要修剪直到看到“\r\n”。 - CMCDragonkai

20

请尝试以下方法:

import pexpect
child = pexpect.spawn('ls')
print child.read() # not readline

read()会给你ls的全部输出。


在我的测试中,对于spawnu也有效,而其他顶级答案则不行。可能需要先验证命令是否已完成,尽管对于ls来说可能并不重要。 - AlanSE

15
#!/usr/bin/env python

import pexpect
child = pexpect.spawn("ssh root@172.16.0.120c -p 2222")
child.logfile = open("/tmp/mylog", "w")
child.expect(".*assword:")
child.send("XXXXXXX\r")
child.expect(".*\$ ")
child.sendline("ls\r")
child.expect(".*\$ ")

前往打开您的日志文件:- 前往终端

$gedit /tmp/mylog

根据https://pexpect.readthedocs.io/en/stable/api/pexpect.html#spawn-class的说明:

# In Python 3, we'll use the ``encoding`` argument to decode data
# from the subprocess and handle it as unicode:
 child = pexpect.spawn('some_command', encoding='utf-8')
 child.logfile = sys.stdout

1
这个例子很容易被用来进行网络钓鱼...只是说一下。 - newshorts
在Python3中,使用open("/tmp/mylog", "wb")可以打开一个文件并获取字节输出。 - Ashwani
@Ashwani 请参考此链接 https://pexpect.readthedocs.io/en/stable/api/pexpect.html#spawn-class - Reegan Miranda

7
我认为你所需要的只有:

我认为你只需要:

p = pexpect.spawn('ls')
p.expect(pexpect.EOF)
print(p.before)

或者

p = pexpect.spawn('/bin/ls')
p.expect(pexpect.EOF)
print(p.before)

或者

p = pexpect.spawn('/bin/bash -c "ls"')
p.expect(pexpect.EOF)
print(p.before)

甚至

print(pexpect.run('ls'))

3

2
注意:如果child.sendline(...)是程序的最后一行,则输出将不会被捕获。期望EOF有所帮助:child.expect(pexpect.EOF)。 http://pexpect.readthedocs.io/en/stable/commonissues.html#truncated-output-just-before-child-exits - Victor Sergienko
@VictorSergienko 已编辑。谢谢! - djhaskin987
1
还有几点需要注意:1. 我会先分配logfile。2. 只有在流实际结束时才能期望EOF。如果我们正在生成一个shell,则必须显式添加exit作为最后一个命令。 - Victor Sergienko
这里并不是生成一个 shell,但这是一个好点。虽然我已经添加了另一件事。 - djhaskin987

1

从类spawn(SpawnBase)的文档中复制,也许example-2是你想要的。

将示例日志输入和输出到文件中:

child = pexpect.spawn('some_command')
fout = open('mylog.txt','wb')
child.logfile = fout

将日志输出到标准输出的示例:

# In Python 2:
child = pexpect.spawn('some_command')
child.logfile = sys.stdout

# In Python 3, we'll use the ``encoding`` argument to decode data
# from the subprocess and handle it as unicode:
child = pexpect.spawn('some_command', encoding='utf-8')
child.logfile = sys.stdout

0
您可以使用一个简单的包tiotrap,其中包含用于管理TextIO流的TextIOTrap助手类。
安装:
python3 -m pip install tiotrap

例如:

tio_trap = tiotrap.TextIOTrap(store=True)
p = pexpect.spawn('ls -la')
p.logfile = tio_trap
p.expect(pexpect.EOF)
print(f"ls output:\n{str(tio_trap)}\n~")

0

对我而言,使用日志文件的方法行不通,因为其中包含了大量我无法摆脱的转义字符。

最终我选择了将命令输出回显,例如如果您的操作系统是Ubuntu:

child.sendline(yourcommand > logfile.txt)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接