Tôi muốn chạy nhiều quy trình song song với khả năng lấy thiết bị xuất chuẩn bất kỳ lúc nào. Tôi nên làm như thế nào? Tôi có cần chạy chuỗi cho mỗi cuộc gọi subprocess.Popen()
không?Quy trình con của Python song song
Trả lời
Bạn có thể làm điều đó trong một chuỗi.
Giả sử bạn có một kịch bản mà in dòng vào những thời điểm ngẫu nhiên:
#!/usr/bin/env python
#file: child.py
import os
import random
import sys
import time
for i in range(10):
print("%2d %s %s" % (int(sys.argv[1]), os.getpid(), i))
sys.stdout.flush()
time.sleep(random.random())
Và bạn muốn thu thập các kết quả ngay sau khi nó trở nên có sẵn, bạn có thể sử dụng trên các hệ thống select
POSIX như @zigg suggested:
#!/usr/bin/env python
from __future__ import print_function
from select import select
from subprocess import Popen, PIPE
# start several subprocesses
processes = [Popen(['./child.py', str(i)], stdout=PIPE,
bufsize=1, close_fds=True,
universal_newlines=True)
for i in range(5)]
# read output
timeout = 0.1 # seconds
while processes:
# remove finished processes from the list (O(N**2))
for p in processes[:]:
if p.poll() is not None: # process ended
print(p.stdout.read(), end='') # read the rest
p.stdout.close()
processes.remove(p)
# wait until there is something to read
rlist = select([p.stdout for p in processes], [],[], timeout)[0]
# read a line from each process that has output ready
for f in rlist:
print(f.readline(), end='') #NOTE: it can block
Một giải pháp di động khác (có thể hoạt động trên Windows, Linux, OSX) có thể sử dụng chuỗi trình đọc cho mỗi quá trình, xem Non-blocking read on a subprocess.PIPE in python.
Dưới đây là os.pipe()
giải pháp dựa trên hoạt động trên Unix và Windows:
#!/usr/bin/env python
from __future__ import print_function
import io
import os
import sys
from subprocess import Popen
ON_POSIX = 'posix' in sys.builtin_module_names
# create a pipe to get data
input_fd, output_fd = os.pipe()
# start several subprocesses
processes = [Popen([sys.executable, 'child.py', str(i)], stdout=output_fd,
close_fds=ON_POSIX) # close input_fd in children
for i in range(5)]
os.close(output_fd) # close unused end of the pipe
# read output line by line as soon as it is available
with io.open(input_fd, 'r', buffering=1) as file:
for line in file:
print(line, end='')
#
for p in processes:
p.wait()
Bạn dường như ghép mọi stdout của trẻ em thành một fd duy nhất (output_fd) trong giải pháp cuối cùng của bạn. Điều gì xảy ra nếu 2 trẻ em in cùng một lúc, điều đó sẽ không làm hỏng đầu ra (ví dụ: 'AAA \ n' + 'BBB \ n' -> 'ABBB \ nAA \ n') – dan3
@ dan3: Đó là một mối quan tâm hợp lệ . 'write' nhỏ hơn' PIPE_BUF' byte là nguyên tử. Nếu không, dữ liệu từ nhiều quy trình có thể được xen kẽ. POSIX yêu cầu ít nhất 512 byte. Trên Linux, 'PIPE_BUF' là 4096 byte. – jfs
Dưới đây là một câu hỏi tương tự mà tôi đã đăng gần đây tại đây, http://stackoverflow.com/questions/36624056/running-a-secondary-script-in-a-new-terminal sẽ thật tuyệt vời nếu bạn có thể giúp đỡ, cảm ơn mọi trường hợp . –
Bạn không cần chạy chuỗi cho từng quy trình. Bạn có thể xem qua các luồng stdout
cho từng quy trình mà không chặn chúng và chỉ đọc từ chúng nếu chúng có sẵn dữ liệu để đọc.
Bạn do phải cẩn thận để không vô tình chặn chúng, tuy nhiên, nếu bạn không có ý định.
Tôi làm 'p = subprocess.Popen (…)' và sau đó 'print p.communicate() [0] 'nhiều lần. Nhưng 'communication()' chỉ đợi trước khi quá trình kết thúc. – sashab
Có, đó là lý do tại sao bạn không thể sử dụng 'communication()' nếu bạn muốn sử dụng một chuỗi đơn. Có nhiều cách khác để lấy stdout ngoài 'communication()'. – Amber
Có thể bạn cần xem xét mô-đun [select] (http://docs.python.org/library/select.html) để chờ nhiều quy trình phụ cùng một lúc. – zigg
Bạn cũng có thể thu thập từ nhiều stdout subprocesses đồng thời sử dụng twisted
:
#!/usr/bin/env python
import sys
from twisted.internet import protocol, reactor
class ProcessProtocol(protocol.ProcessProtocol):
def outReceived(self, data):
print data, # received chunk of stdout from child
def processEnded(self, status):
global nprocesses
nprocesses -= 1
if nprocesses == 0: # all processes ended
reactor.stop()
# start subprocesses
nprocesses = 5
for _ in xrange(nprocesses):
reactor.spawnProcess(ProcessProtocol(), sys.executable,
args=[sys.executable, 'child.py'],
usePTY=True) # can change how child buffers stdout
reactor.run()
- 1. Xử lý đa Python cho các quy trình song song
- 2. Song song các quy trình PHP bằng Tập lệnh Bash?
- 3. GNU tăng tốc tạo quy trình xây dựng - Song song?
- 4. Thực thi song song các quy trình vỏ
- 5. Song song lồng nhau trong Python
- 6. Lập trình động song song
- 7. Các vấn đề lập trình song song
- 8. Song song trình tạo chuỗi Fibonacci
- 9. Python: Biên dịch các regex song song
- 10. LinqToSql - Song song - DataContext và song song
- 11. bản đồ song song python (multiprocessing.Pool.map) với dữ liệu chung
- 12. Python song song: Gọi lại là gì?
- 13. SqlConnection với lập trình song song
- 14. Lập trình song song chung Lisp
- 15. Lập trình song song trong C#
- 16. Lập trình song song và C++
- 17. Xóa các quá trình zombie bằng gói song song
- 18. Song song OpenMP trên chức năng đệ quy
- 19. Các chuỗi python GAE không thực hiện song song
- 20. Python, chạy các công cụ dòng lệnh song song
- 21. Sử dụng One Kinect cho Windows cho hai quy trình song song
- 22. In ấn để stdout trong các quy trình song song IPython
- 23. Luồng song song với Xử lý song song
- 24. OpenMP - Chạy mã song song bên trong mã song song
- 25. Lập trình song song == lập trình đa luồng?
- 26. chạy song song AsyncTask
- 27. Dùng fork trong Ruby on Rails để tạo quy trình song song
- 28. Repa Không song song
- 29. song song javascript
- 30. Bộ lặp song song
bản sao có thể có của [cách chạy một số tệp thực thi bằng python?] (Http://stackoverflow.com/questions/9724499/how-to-run-several-executable-using-python) –
liên quan: Đây là cách để [ chạy nhiều lệnh shell (và tùy chọn bắt đầu ra) đồng thời] (http://stackoverflow.com/a/23616229/4279) – jfs