簡體   English   中英

使用子進程的Python parallel.futures,運行多個python腳本

[英]Python concurrent.futures using subprocess, running several python script

我想使用current.futures同時運行多個python腳本。 我的代碼的串行版本去查找文件夾中的特定python文件並執行它。

import re
import os
import glob
import re
from glob import glob
import concurrent.futures as cf

FileList = [];
import time
FileList = [];
start_dir = os.getcwd();
pattern   = "Read.py"

for dir,_,_ in os.walk(start_dir):
    FileList.extend(glob(os.path.join(dir,pattern))) ;

FileList

i=0
for file in FileList:
    dir=os.path.dirname((file))
    dirname1 = os.path.basename(dir) 
    print(dirname1)
    i=i+1
    Str='python '+ file
    print(Str)
    completed_process = subprocess.run(Str)`

對於我的代碼的並行版本:

    def Python_callback(future):
    print(future.run_type, future.jid)
    return "One Folder finished executing"

def Python_execute():
    from concurrent.futures import ProcessPoolExecutor as Pool
    args = FileList
    pool = Pool(max_workers=1)
    future = pool.submit(subprocess.call, args, shell=1)
    future.run_type = "run_type"
    future.jid = FileList
    future.add_done_callback(Python_callback)
    print("Python executed")

if __name__ == '__main__':
    import subprocess
    Python_execute()

問題是我不確定如何將FileList的每個元素傳遞給單獨的cpu

謝謝您的幫助

最小的更改是對每個元素使用一次submit ,而不是對整個列表使用一次:

futures = []
for file in FileList:
    future = pool.submit(subprocess.call, file, shell=1)
    future.blah blah
    futures.append(future)

僅當您要對期貨執行某些操作時才需要futures列表,例如等待它們完成,檢查其返回值等。

同時,您正在使用max_workers=1顯式創建池。 毫不奇怪,這意味着您只會得到1個輔助子進程,因此它將最終等待一個子進程完成,然后再獲取下一個子進程。 如果要實際同時運行它們,請刪除該max_workers並將其默認為每個內核一個(或通過max_workers=8或其他一些不為1 (如果有充分的理由覆蓋默認值))。


在進行此操作時,有很多方法可以簡化您的工作:

  • 您真的需要在這里進行multiprocessing嗎? 如果您需要與每個子流程進行通信,那么在單個線程中執行該操作可能會很痛苦,但是線程或asyncio工作原理與此處的流程一樣好。
  • 更重要的是,看起來您實際上並不需要任何東西,但可以啟動該過程並等待其完成,而這可以用簡單的同步代碼完成。
  • 為什么要構建一個字符串並使用shell=1而不是僅僅傳遞一個列表而不使用shell? 使用外殼不必要地產生了開銷,安全問題和調試煩惱。
  • 你真的不需要jid每個未來它只是所有調用的字符串,不能是有用的列表。 可能更有用的是某種標識符或子流程的返回代碼,或者……可能還有很多其他事情,但這些都是可以通過讀取subprocess.call的返回值或簡單的包裝器來完成的。
  • 您真的也不需要回調。 如果您僅將所有期貨收集在一個列表中並as_completed ,則可以更簡單地顯示結果。
  • 如果您同時執行上述pool.submit ,則循環內只剩下一個pool.submit了,這意味着您可以用pool.map替換整個循環。
  • 您很少或不需要將os.walkglob混合使用。 當您實際上具有全局模式時,將fnmatch應用於os.walkfiles列表。 但是在這里,您只是在每個目錄中查找特定的文件名,因此,實際上,您需要過濾的只是file == 'Read.py'
  • 您沒有在循環中使用i 但是,如果確實需要,最好for i, file in enumerate(FileList):執行for i, file in enumerate(FileList): for file in FileList:而不要for file in FileList:然后手動增加i

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM