[英]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.