![](/img/trans.png)
[英]What's the best way to share a dictionary between multiple Python processes?
[英]Best way to fork multiple shell commands/processes in Python?
我在os.fork
和os.fork
/ multiprocessing模塊上看到的大多數示例都展示了如何派生調用Python腳本或Python代碼塊的新實例。 並發生成一組任意shell命令的最佳方法是什么?
我想,我可以只使用subprocess.call
或Popen
命令之一並將輸出通過管道傳輸到文件,我相信該文件將立即返回,至少返回給調用者。 我知道這並不難做到,我只是想找出最簡單,最Python的方式來做到這一點。
提前致謝
對subprocess.Popen
所有調用都會立即返回給調用者。 是wait
和communicate
哪個塊的電話。 因此,您需要做的就是使用subprocess.Popen
(為安全起見將stdin設置為/ dev / null)啟動多個進程,然后一個個地調用進行communicate
直到它們全部完成為止。
自然地,我假設您只是嘗試啟動一堆不相關的命令(即未通過管道傳輸)。
我想,我可以只給我們subprocess.call或Popen命令之一,然后將輸出通過管道傳遞到文件,我相信它將立即返回,至少返回給調用者。
如果要處理數據,那不是一個好方法。
在這種情況下,最好做
sp = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
然后使用sp.communicate()
或直接從sp.stdout.read()
讀取。
如果以后要在調用程序中處理數據,則有兩種處理方法:
您可以通過一個單獨的線程盡快檢索數據,讀取數據並將其存儲在消費者可以獲取的位置。
您可以讓生產子流程具有block並在需要時從中檢索數據。 子進程將產生盡可能多的數據,以適合管道緩沖區(通常為64 kiB),然后在進一步寫入時阻塞。 一旦需要數據,就從子進程對象的stdout
(也可能是stderr
read()
並使用它們-或者,稍后再使用sp.communicate()
。
如果生成數據需要很多時間,那么方法1將會走,所以您的wprogram必須等待。
如果數據的大小非常大和/或數據生成的速度太快以至於緩沖將毫無意義,則將首選方法2。
我喜歡使用PTY而不是管道。 對於一堆只希望捕獲錯誤消息的過程,我這樣做了。
RNULL = open('/dev/null', 'r')
WNULL = open('/dev/null', 'w')
logfile = open("myprocess.log", "a", 1)
REALSTDERR = sys.stderr
sys.stderr = logfile
下一部分是一個循環,產生約30個進程。
sys.stderr = REALSTDERR
master, slave = pty.openpty()
self.subp = Popen(self.parsed, shell=False, stdin=RNULL, stdout=WNULL, stderr=slave)
sys.stderr = logfile
之后,我有了一個select
循環,該循環收集了所有錯誤消息並將其發送到單個日志文件。 使用PTY意味着我不必擔心部分線會混淆,因為線規提供了簡單的框架。
在所有可能的情況下都沒有最好的方法。 最好取決於手頭的問題。
這是生成程序並將其輸出保存到結合stdout / stderr的文件中的方法:
import subprocess
import sys
def spawn(cmd, output_file):
on_posix = 'posix' in sys.builtin_module_names
return subprocess.Popen(cmd, close_fds=on_posix, bufsize=-1,
stdin=open(os.devnull,'rb'),
stdout=output_file,
stderr=subprocess.STDOUT)
要生成可以與腳本以及彼此並行運行的多個進程,請執行以下操作:
processes, files = [], []
try:
for i, cmd in enumerate(commands):
files.append(open('out%d' % i, 'wb'))
processes.append(spawn(cmd, files[-1]))
finally:
for p in processes:
p.wait()
for f in files:
f.close()
注意: cmd
到處都是列表。
要生成多個並發命令,您將需要更改類RunCmd來實例化多個讀取輸出/寫入輸入隊列並生成多個Popen子進程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.