簡體   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