2013-07-01 36 views
17

Đây là theo dõi tới this question, nhưng nếu tôi muốn chuyển đối số đến stdin đến subprocess, làm cách nào để có được kết quả trong thời gian thực? Đây là những gì tôi hiện có; Tôi cũng đã thử thay thế Popen bằng call từ mô-đun subprocess và điều này chỉ dẫn đến tập lệnh treo.in stdout trong thời gian thực từ một tiến trình con yêu cầu stdin

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 

Trong câu hỏi cũ mà tôi không cần phải vượt qua stdin Tôi đã đề nghị sử dụng p.stdout.readline, có không có chỗ đó để bất cứ điều gì để ống stdin.

Phụ lục: Tính năng này hoạt động để chuyển, nhưng tôi chỉ thấy đầu ra ở cuối và tôi muốn xem chi tiết về quá trình chuyển trong khi nó đang diễn ra.

+0

nếu tất cả các bạn muốn là để xem kết quả sau đó chỉ cần thả 'stdout = PIPE'. – jfs

Trả lời

25

Để lấy stdout từ tiến trình con trong thời gian thực, bạn cần phải quyết định chính xác những gì bạn muốn hành vi; cụ thể, bạn cần quyết định xem bạn có muốn xử lý dòng đầu ra theo dòng hoặc ký tự theo ký tự hay không và liệu bạn có muốn chặn trong khi chờ kết quả đầu ra hoặc có thể thực hiện điều gì khác trong khi chờ đợi hay không.

Dường như nó có lẽ sẽ đủ cho trường hợp của bạn để đọc các đầu ra trong thời trang dòng đệm, ngăn chặn cho đến khi mỗi dòng hoàn toàn do thỏa thuận, có nghĩa là các chức năng thuận tiện cung cấp bởi subprocess là tốt đủ:

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() 

Nếu bạn cần ghi vào stdin của quá trình, chỉ cần sử dụng một ống:

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() 

Pace câu trả lời khác, không có cần phải gián tiếp thông qua một tập tin trong để chuyển đầu vào cho tiến trình con.

+0

i dunno tôi couldnt có được 'sys.stdin.read()' để trả lại bất cứ điều gì trong tập tin được gọi với python2. 6 với phương pháp này ... đó là lý do tại sao tôi không đưa nó như là một câu trả lời ...nhưng có lẽ tôi đã phá vỡ một cái gì đó. –

+1

Khi được gọi không có đối số 'read()' sẽ không trả về cho đến khi nó gặp 'EOF' (nó đang cố gắng đọc toàn bộ đối tượng tệp mà nó được gọi, và nó không biết nó đã tiêu thụ tất cả tập tin cho đến khi nó đạt 'EOF'). Đó là hiếm khi hành vi người ta muốn khi đọc đầu vào. Bạn nên truyền một số byte được chỉ định làm đối số cho 'read()' (trong trường hợp đó lệnh 'read()' sẽ trả về sau khi gặp phải số byte đó hoặc 'EOF', tùy điều kiện nào đến trước) hoặc sử dụng' readline () '(mà sẽ trở lại sau khi gặp phải một dòng mới). – Alp

+0

ok +1 phù hợp của bạn cho thanh toán bù trừ rằng lên –

2

một cái gì đó như thế này tôi nghĩ

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() 

sử dụng một iterator sẽ trả lại kết quả trực tiếp về cơ bản ..

để gửi đầu vào stdin bạn sẽ cần một cái gì đó giống như

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) 

này sẽ tương tự như lệnh shell linux của

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

thấy dãy Alps trả lời cho qua tốt hơn để stdin

+0

Cảm ơn, đây là câu trả lời được đưa ra trong câu hỏi trước đây của tôi, nơi tôi không cần 'stdin', nhưng tôi không biết cách chuyển cho đối số 'đầu vào' như tôi 'p.communicate' – hatmatrix

+0

xem chỉnh sửa. .. bạn sẽ cần phải đặt chuỗi đầu vào trong một tập tin và vượt qua một filehandler mở để đối số stdin của constructor –

1

Nếu bạn vượt qua tất cả các đầu vào của bạn trước khi bắt đầu đọc kết quả và nếu bởi "thời gian thực" bạn có nghĩa là bất cứ khi nào tiến trình con xả đệm stdout của nó:

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()