繁体   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