Python concurrent.futures使用子流程,运行多个Python脚本

Python concurrent.futures使用子流程,运行多个Python脚本,python,subprocess,concurrent.futures,process-pool,Python,Subprocess,Concurrent.futures,Process Pool,我想使用concurrent.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 = "Rea

我想使用concurrent.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()
问题是,我不确定如何将文件列表的每个元素传递给单独的cpu


提前感谢您的帮助

最小的更改是对每个元素使用一次
提交
,而不是对整个列表使用一次:

futures = []
for file in FileList:
    future = pool.submit(subprocess.call, file, shell=1)
    future.blah blah
    futures.append(future)
只有当你想对期货做一些事情,等待期货完成,检查其返回值等时,才需要
期货
列表

同时,您正在显式地使用
max\u workers=1
创建池。毫不奇怪,这意味着您将只获得一个工作子进程,因此它将在获取下一个子进程之前等待一个子进程完成。如果要同时运行它们,请删除该
max_-workers
,并将其默认为每个核心一个(或者传递
max_-workers=8
或其他非
1
的数字,如果您有充分的理由覆盖默认值)


在我们进行这项工作时,有很多方法可以简化您的工作:

  • 您真的需要这里的
    多处理
    ?如果您需要与每个子进程通信,在单个线程中进行通信可能会很痛苦,但是线程,或者
    asyncio
    ,将与这里的进程一样工作
  • 更重要的是,看起来您实际上并不需要任何东西,只需要启动流程并等待它完成,这可以通过简单的同步代码完成
  • 为什么要构建一个字符串并使用
    shell=1
    ,而不是只传递一个列表而不使用shell?不必要地使用shell会产生开销、安全问题和调试麻烦
  • 你真的不需要在以后的每一天使用
    jid
    ,它只是你所有调用字符串的列表,这是没有用的。更有用的可能是某种标识符,或者子流程返回代码,或者…可能还有很多其他的东西,但是这些都可以通过读取
    subprocess.call的返回值来完成,或者是一个简单的包装器
  • 你真的不需要回调。如果你只是把所有的未来都收集到一个列表中,然后在你完成的时候打印出来,你就可以更简单地打印结果了
  • 如果您同时执行上述两项操作,则除了循环中的
    池。submit
    ,您就什么都没有了,这意味着您可以将整个循环替换为
    池。map
  • 您很少需要或希望混合使用
    os.walk
    glob
    。当您实际拥有一个全局模式时,在
    os.walk
    文件
    列表上应用
    fnmatch
    。但是在这里,您只需要在每个目录中查找特定的文件名,所以实际上,您只需要筛选
    file==“Read.py”
  • 您没有在循环中使用
    i
    。但如果您确实需要它,最好为i执行
    ,在enumerate(FileList)中为file执行
    ,而不是为FileList中的file执行
    并手动递增一个
    i