执行并行 .py 脚本

Execute parallell .py scripts

说我有 scrapper_1.py , scrapper_2.py, scrapper_3.py.

我 运行 现在它来自 pycharm run/execute 每个单独的方式,这样我可以在任务管理器中看到 3 python.exe 正在执行。

现在我正在尝试编写一个主脚本,比如 scrapper_runner.py 将此报废程序作为模块导入,并且 运行 它们都是并行的而不是顺序的。

我尝试了来自各种 SO 帖子的子进程、多处理甚至 os.system 的示例......但没有任何运气......从日志中它们都是 运行 按顺序和任务管理器我只看到一次 python.exe 次执行。

这种流程的模式是否正确?

编辑:1(尝试使用 concurrent.futures ProcessPoolExecutor)按顺序 运行ns。

from concurrent.futures import ProcessPoolExecutor

import scrapers.scraper_1 as scraper_1
import scrapers.scraper_2 as scraper_2
import scrapers.scraper_3 as scraper_3

## Calling method runner on each scrapper_x to kick off processes
runners_list = [scraper_1.runner(), scraper_1.runner(), scraper_3.runner()]



if __name__ == "__main__":


    with ProcessPoolExecutor(max_workers=10) as executor:
        for runner in runners_list:
            future = executor.submit(runner)
            print(future.result())

python 中的子进程可能会或可能不会显示为单独的进程,具体取决于您的 OS 和任务管理器。例如linux中的htop,将在树视图中显示父进程下的子进程。

我建议看一下 python 中 multiprocessing 模块的深入教程:https://pymotw.com/2/multiprocessing/basics.html

但是,如果 python 的 multiprocessing/threading 内置方法对您不起作用或没有意义,您可以通过使用 bash 调用来实现您想要的结果你的 python 脚本。以下 bash 脚本会产生附加的屏幕截图。

#!/bin/sh
./py1.py &
./py2.py &
./py3.py &

说明:每个调用结束时的 & 告诉 bash 到 运行 每个调用作为后台进程。

您的问题在于如何设置流程。你不是 运行 并行的进程,即使你认为你是。你实际上是 运行 他们,当你将它们添加到 runners_list 然后你是 运行 每个跑步者作为多进程并行的结果。

您想要做的是将函数添加到 runners_list 而不执行它们,然后让它们在您的多处理 pool 中执行。实现这一点的方法是添加函数引用,即函数的名称。为此,您不应包含括号,因为这是调用函数的语法,而不仅仅是命名它们。

此外,要让期货异步执行,直接调用 future.result 是不可能的,因为这会强制代码按顺序执行,以确保结果在与调用函数的顺序相同。

这意味着您的问题的答案是

from concurrent.futures import ProcessPoolExecutor

import scrapers.scraper_1 as scraper_1
import scrapers.scraper_2 as scraper_2
import scrapers.scraper_3 as scraper_3

## NOT calling method runner on each scrapper_x to kick off processes
## Instead add them to the list of functions to be run in the pool
runners_list = [scraper_1.runner, scraper_1.runner, scraper_3.runner]

# Adding callback function to call when future is done.
# If result is not printed in callback, the future.result call will
# serialize the call sequence to ensure results in order
def print_result(future):
    print(future.result)

if __name__ == "__main__":
    with ProcessPoolExecutor(max_workers=10) as executor:
        for runner in runners_list:
            future = executor.submit(runner)
            future.add_done_callback(print_result)

如您所见,此处运行者的调用不会在创建列表时发生,而是在稍后将 runner 提交给执行程序时发生。并且,当结果准备就绪时,将调用回调以将结果打印到屏幕。