2013-07-01 66 views
17

這是this question的後續操作,但是如果我想將參數傳遞到stdinsubprocess,我怎樣才能實時獲得輸出?這是我目前所擁有的;我也嘗試用subprocess模塊替換Popencall,這隻會導致腳本掛起。從需要stdin的子進程中實時打印stdout

from subprocess import Popen, PIPE, STDOUT 
cmd = 'rsync --rsh=ssh -rv --files-from=- thisdir/ servername:folder/' 
p = Popen(cmd.split(), stdout=PIPE, stdin=PIPE, stderr=STDOUT) 
subfolders = '\n'.join(['subfolder1','subfolder2']) 
output = p.communicate(input=subfolders)[0] 
print output 

在前發問,我沒要過stdin我建議使用p.stdout.readline,有沒有房有沒有管什麼stdin

附錄:這適用於轉移,但我只在最後看到輸出,我希望在轉移發生時看到轉移的詳細信息。

+0

如果你想要的是看到輸出那麼就放下'stdout = PIPE'。 – jfs

回答

25

爲了從你需要決定你想要什麼行爲實時子進程的stdout搶;具體而言,您需要決定是否要逐行處理輸出或按字符處理輸出,以及在等待輸出時是要阻止還是在等待時能夠執行其他操作。

它看起來像它可能會足以滿足你的情況下讀取行緩衝方式輸出,阻塞,直到每個整條生產線進來,這意味着由subprocess提供的便利功能不夠好:

p = subprocess.Popen(some_cmd, stdout=subprocess.PIPE) 
# Grab stdout line by line as it becomes available. This will loop until 
# p terminates. 
while p.poll() is None: 
    l = p.stdout.readline() # This blocks until it receives a newline. 
    print l 
# When the subprocess terminates there might be unconsumed output 
# that still needs to be processed. 
print p.stdout.read() 

如果你需要寫入過程的標準輸入,只需使用另一管道:

p = subprocess.Popen(some_cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE) 
# Send input to p. 
p.stdin.write("some input\n") 
p.stdin.flush() 
# Now start grabbing output. 
while p.poll() is None: 
    l = p.stdout.readline() 
    print l 
print p.stdout.read() 

佩斯對方的回答,沒有必要間接通過一個文件爲了將輸入傳遞給子進程。

+0

我不知道我不能讓'sys.stdin.read()'用python2返回被調用文件中的任何東西。 6用這種方法...這就是爲什麼我沒有把這作爲一個答案...但也許我打破了一些東西。 –

+1

當沒有參數調用時,read()只有在遇到EOF時纔會返回(它試圖讀取它所調用的文件對象的全部內容,並且它不知道它會消耗所有的文件直到它達到'EOF')。閱讀輸入時,這很少是人們想要的行爲。您應該將指定數量的字節作爲參數傳遞給'read()'(在這種情況下,read()'調用將在遇到字節數或EOF後返回),或者使用readline )'(遇到換行符後會返回)。 – Alp

+0

確定您的權利+1感謝您清除 –

2

這樣的事情,我認爲

from subprocess import Popen, PIPE, STDOUT 

p = Popen('c:/python26/python printingTest.py', stdout = PIPE, 
     stderr = PIPE) 
for line in iter(p.stdout.readline, ''): 
    print line 
p.stdout.close() 

使用迭代器將返回基本上實時的結果..

,以輸入發送給標準輸入你需要像

other_input = "some extra input stuff" 
with open("to_input.txt","w") as f: 
    f.write(other_input) 
p = Popen('c:/python26/python printingTest.py < some_input_redirection_thing', 
     stdin = open("to_input.txt"), 
     stdout = PIPE, 
     stderr = PIPE) 

這會類似於linux的shell命令

%prompt%> some_file.o < cat to_input.txt 

看到阿爾卑斯山的回答更好的通過對標準輸入

+0

謝謝,這是我在上一個問題中給出的答案,我不需要'stdin',但我不知道如何將'input'參數傳遞給它,因爲我會'p.communicate' – hatmatrix

+0

參見編輯。 ..你需要把輸入字符串放在一個文件中,並將一個打開的文件處理程序傳遞給構造函數的stdin參數 –

1

如果你開始讀通過「實時」的輸出,如果前通過所有的輸入您的意思是,只要子進程刷新其標準輸出緩衝區:

from subprocess import Popen, PIPE, STDOUT 

cmd = 'rsync --rsh=ssh -rv --files-from=- thisdir/ servername:folder/' 
p = Popen(cmd.split(), stdout=PIPE, stdin=PIPE, stderr=STDOUT, bufsize=1) 
subfolders = '\n'.join(['subfolder1','subfolder2']) 
p.stdin.write(subfolders) 
p.stdin.close() # eof 
for line in iter(p.stdout.readline, ''): 
    print line, # do something with the output here 
p.stdout.close() 
rc = p.wait()