簡體   English   中英

Python 子進程標准輸出不捕獲輸入提示

[英]Python subprocess stdout doesn't capture input prompt

我正在使用 subprocess 生成一個conda create命令並捕獲生成的stdout供以后使用。 我還立即將stdout打印到控制台,以便用戶仍然可以看到子進程的進度:

p = subprocess.Popen('conda create -n env1 python', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(p.stdout.readline, b''):
    sys.stdout.write(line.decode(sys.stdout.encoding))

這工作正常,直到conda create需要用戶輸入時執行到一半:它提示Proceed (n/y)? 並等待用戶輸入選項。 但是,上面的代碼不會打印提示,而只是等待“在空白屏幕上”輸入。 收到輸入,將打印提示,然后按預期繼續執行。

我假設這是因為輸入以某種方式阻止了將提示寫入stdout ,因此在解除輸入塊之前, readline不會接收新數據。

有沒有辦法確保在子進程等待用戶輸入之前打印輸入提示? 注意我在 Windows 上運行。

雖然我確信 pexpect 在這種情況下會起作用,但我認為這會有點矯枉過正。 相反,我使用了 MisterMiyagi 的見解並將readline替換為read

最終代碼是這樣的:

p = subprocess.Popen('conda create -n env1 python', stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
while p.poll() is None:
    sys.stdout.write(p.stdout.read(1).decode(sys.stdout.encoding))
    sys.stdout.flush()

請注意read(1) ,因為僅使用read()會阻塞 while 循環,直到找到 EOF。 如果在輸入提示之前沒有發現 EOF,則根本不會打印任何內容,此外,調用flush可確保寫入sys.stdout的文本在屏幕上實際可見。

對於這個用例,我建議使用pexpect 標准輸入!=標准輸出

有條件地根據stdout上的提示發送到stdin的示例用例

def expectgit(alog):
    TMPLOG = "/tmp/pexpect.log"
    cmd = f'''
ssh -T git@github.com ;\
echo "alldone" ;
'''
    with open(TMPLOG, "w") as log:
        ch = pexpect.spawn(f"/bin/bash -c \"{cmd}\"", encoding='utf-8', logfile=log)
        while True:
            i = ch.expect(["successfully authenticated", "Are you sure you want to continue connecting"])
            if i == 0:
                alog.info("Git all good")
                break
            elif i == 1:
                alog.info("Fingerprint verification")
                ch.send("yes\r")
        ch.expect("alldone")
        i = ch.expect([pexpect.EOF], timeout=5)
        ch.close()
        alog.info("expect done - EOF")

    with open(TMPLOG) as log:
        for l in log.readlines():
            alog.debug(l.strip())

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM