Python concurrent.futures使用子流程,运行多个Python脚本
我想使用concurrent.futures同时运行几个python脚本。 我的代码的串行版本在文件夹中查找特定的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
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