繁体   English   中英

Pexpect多线Output

[英]Pexpect Mulitple Line Output

问题

如何使用 pexpect 获得具有多行 output 的命令的 output?

例子

此代码有效,尽管 output 被砸成一行:

child = pexpect.spawn('ping -c 3 1.1.1.1')
child.expect(pexpect.EOF)
print(child.before)

但是,此代码不起作用:

child = pexpect.spawn('hostname')
child.expect(pexpect.EOF)
print(child.before)

child.seldline('ping -c 3 1.1.1.1')
child.expect(pexpect.EOF)
print(child.before)

我将如何让第二个代码工作?

背景

我有我需要运行才能连接的命令(此处替换为主机名),然后是 output 多行命令(此处替换为 ping),我似乎无法从中获取 output。 如果我查找 EOF 以外的任何字符串,我会收到 EOF 异常...

如果您需要证明,我实际运行的命令在这里:

这个其他问题的答案可能会被弃用,因为这部分代码完全复制只是一遍又一遍地输出b''

默认情况下,数据是bytes ,而不是str 这就是为什么“output砸成一行”的原因。 请参见以下示例:

$ cat foo.py
import pexpect

child = pexpect.spawn('ping -c 2 127.0.0.1')
child.expect(pexpect.EOF)
print(child.before)


$ python3 foo.py
b'PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.\r\n64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.027 ms\r\n64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.056 ms\r\n\r\n--- 127.0.0.1 ping statistics ---\r\n2 packets transmitted, 2 received, 0% packet loss, time 30ms\r\nrtt min/avg/max/mdev = 0.027/0.041/0.056/0.015 ms\r\n'
$

打印时可以decode()

$ cat foo.py
import pexpect

child = pexpect.spawn('ping -c 2 127.0.0.1')
child.expect(pexpect.EOF)
print(child.before.decode(encoding='utf8') )  # utf8 is the default for bytes.decode()


$ python3 foo.py
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.024 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.054 ms

--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 11ms
rtt min/avg/max/mdev = 0.024/0.039/0.054/0.015 ms

$

或者您可以在调用spawn()时指定编码:

$ cat foo.py
import pexpect

child = pexpect.spawn('ping -c 2 127.0.0.1', encoding='utf8')
child.expect(pexpect.EOF)
print(child.before)


$ python3 foo.py
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.036 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.053 ms

--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 20ms
rtt min/avg/max/mdev = 0.036/0.044/0.053/0.010 ms

$

生成一个将保持打开状态的 PID

真正的问题:为什么第二个例子不起作用。

pexpect.spawn object(此处为“孩子”)指向进程 ID(PID)。 我尝试使用的示例不起作用,因为hostname正在运行然后退出。 在我的实际用例中,我使用ssh ,然后在长 output 命令之前使用了其他几个必要步骤(在此处由ping表示)。

使用持续运行的命令启动多步骤流程将解决该问题。 这些示例中的任何一个都可以使用:

child = pexpect.spawn('ssh user@host')
child = pexpect.spawn('bin/bash')

我切换到后者,它启动了一个我可以与之交互的新 shell。 这使我可以向 ssh 连接添加一些错误处理,并在一个 shell 中多次重用代码。

请注意,如果您分别退出 ssh 连接或 bash shell 连接,则需要生成一个新的“孩子”来发送更多命令。

使用非阻塞读取

额外细节:修复第一个/工作示例的 output。

A 此代码将返回最后一个命令的 output 而不会更改它。

def try_read(child):
    """Based on pexpect.pxssh.try_read_prompt"""
    total_timeout = 3
    timeout = 0.5
    inter_char_timeout = 0.1
    begin = time.time()
    expired = 0
    prompt = ''
    while expired < total_timeout:
        try:
            prompt += child.read_nonblocking(size=1, timeout=timeout)
            expired = time.time() - begin # updated total time expired
            timeout = inter_char_timeout
        except TimeoutError:
            print("read ended with TimeoutError")
            break
        except pexpect.TIMEOUT:
            print("read ended with pexpect.Timeout")
            break
        except pexpect.EOF:
            print("read ended with pexpect.EOF")
            break
    return prompt

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM