我想從子進程獲取輸出,然後根據前面的輸出爲該進程提供命令。當程序需要進一步輸入時,我需要做這個可變的次數。 (如果可能,我還需要能夠隱藏子進程命令提示符)。從python子進程獲取輸出並給出命令
我覺得這將是一件容易的事,因爲我已經看到這個問題在2003年的帖子中討論過,它接近2012年,它似乎是一個相當普遍的需求,真的好像它應該是一個基本的部分任何編程語言。顯然,我錯了,不知何故,差不多9年後,仍然沒有以穩定,非破壞性,獨立於平臺的方式完成這項任務的標準方法!
我對文件I/O和緩衝或線程並不十分了解,所以我寧願選擇一個儘可能簡單的解決方案。如果有一個模塊實現了與python 3.x兼容的模塊,我將非常樂意下載它。我意識到有多個問題基本上提出了同樣的問題,但我還沒有找到解決我試圖完成的簡單任務的答案。
這是我迄今爲止基於各種來源的代碼;但是我絕對不知道下一步該怎麼做。我所有的嘗試都以失敗告終,有些設法使用了我CPU的100%(基本上什麼都不做),並且不會退出。
import subprocess
from subprocess import Popen, PIPE
p = Popen(r'C:\postgis_testing\shellcomm.bat',stdin=PIPE,stdout=PIPE,stderr=subprocess.STDOUT shell=True)
stdout,stdin = p.communicate(b'command string')
如果我的問題是不清楚我張貼的樣本批處理文件中,我展示了一種情況,即有必要多個命令發送給子進程(如果你輸入了不正確的命令字符串程序文字循環)。
@echo off
:looper
set INPUT=
set /P INPUT=Type the correct command string:
if "%INPUT%" == "command string" (echo you are correct) else (goto looper)
如果有人可以幫助我,我會非常感激,我相信很多人也會這樣!這裏
編輯是使用eryksun的代碼(下一篇文章)的功能代碼:
import subprocess
import threading
import time
import sys
try:
import queue
except ImportError:
import Queue as queue
def read_stdout(stdout, q, p):
it = iter(lambda: stdout.read(1), b'')
for c in it:
q.put(c)
if stdout.closed:
break
_encoding = getattr(sys.stdout, 'encoding', 'latin-1')
def get_stdout(q, encoding=_encoding):
out = []
while 1:
try:
out.append(q.get(timeout=0.2))
except queue.Empty:
break
return b''.join(out).rstrip().decode(encoding)
def printout(q):
outdata = get_stdout(q)
if outdata:
print('Output: %s' % outdata)
if __name__ == '__main__':
#setup
p = subprocess.Popen(['shellcomm.bat'], stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
bufsize=0, shell=True) # I put shell=True to hide prompt
q = queue.Queue()
encoding = getattr(sys.stdin, 'encoding', 'utf-8')
#for reading stdout
t = threading.Thread(target=read_stdout, args=(p.stdout, q, p))
t.daemon = True
t.start()
#command loop
while p.poll() is None:
printout(q)
cmd = input('Input: ')
cmd = (cmd + '\n').encode(encoding)
p.stdin.write(cmd)
time.sleep(0.1) # I added this to give some time to check for closure (otherwise it doesn't work)
#tear down
for n in range(4):
rc = p.poll()
if rc is not None:
break
time.sleep(0.25)
else:
p.terminate()
rc = p.poll()
if rc is None:
rc = 1
printout(q)
print('Return Code: %d' % rc)
然而,當腳本是從命令運行提示會發生以下情況:
C:\Users\username>python C:\postgis_testing\shellcomm7.py
Input: sth
Traceback (most recent call last):
File "C:\postgis_testing\shellcomm7.py", line 51, in <module>
p.stdin.write(cmd)
IOError: [Errno 22] Invalid argument
看來,程序在從命令提示符運行時關閉。有任何想法嗎?
非常感謝你爲這個它完全處於空閒,但是當我運行修改後的代碼(見我在原來的職位編輯)它給了我下面的錯誤 C:\ Users \用戶名>蟒蛇Ç :\ postgis_testing \ shellcomm7.py 輸入:某物 回溯(最近通話最後一個): 文件 「C:\ postgis_testing \ shellcomm7.py」 51行,在 p.stdin.write(CMD) IO錯誤: [Errno 22]無效的參數 從命令提示符運行時,程序似乎關閉。有任何想法嗎? –
THX1138
@ THX1138:我修改了循環以查詢進程並在請求輸入之前檢查stdin。如果流程退出,它會中斷。我也從'read_stdout'參數中刪除了過程對象;它在我的初稿中錯誤地留下了。 – eryksun
當我從命令提示符運行新代碼時,出現以下錯誤: C:\ Users \ username> python C:\ postgis_testing \ shellcomm8.py Traceback(最近調用最後一次): 文件「C:\ postgis_testing \ shellcomm8.py 「第38行,在 BUFSIZE = 0) 文件 」C:\ Python32 \ lib中\ subprocess.py「,線路741,在__init__ restore_signals,start_new_session) 文件」 C:\ Python32 \ lib中\ subprocess.py「,第960行,在_execute_child startupinfo) WindowsError:[錯誤2]系統找不到指定的文件 –
THX1138