运行 来自另一个 .py 的多个 .py 同时带有参数和超时

Run multiple .py from another .py simultaneously with arguments and timeout

我有一个程序,比方说“main.py”,它 运行 通过参数“python main.py 3”或者,例如,“python main.py 47",这意味着 运行 在程序本身内部设置一个特定的 ID。

我正在尝试编写另一个脚本,比方说“start.py”,以便它启动一定数量的此类程序。如果在start.py里面我写了threads = 4,timeout = 5,那么应该运行 "python main.py 1", "python main.py 2", "python main.py 3", "python main.py 4" 同时执行,但每个命令之间有 5 秒的延迟。

我知道如何在一个线程中执行此操作,但在前一个线程完成之前没有其他参数 运行。

threads = 4
id = 1
for i in range(threads):
    os.system(f"python main.py {id}")
    id += 1
    time.sleep(5)

我正在尝试通过多处理来执行此操作,但我失败了。实现这个的最佳方法是什么,我的方向是否正确?

我已经通过 bash 完成了此操作,但我只需要在 Python 中完成即可。

for ((i=1; i<=4; i++))
do
    python3 main.py "$i" &
done

如果您不想或不能对 main.py 进行更改,那么您可以对当前代码进行的最简单的更改就是简单地执行system 在一个线程中调用,这样你就不会阻塞:

from threading import Thread
import os
import time

def run_main(id):
    os.system(f"python main.py {id}")

threads = 4
id = 1
started_threads = []
for i in range(threads):
    if i != 0:
        time.sleep(5)
    t = Thread(target=run_main, args=(id,))
    t.start()
    started_threads.append(t)
    id += 1
for t in started_threads:
    t.join()

请注意,我已将呼叫移至 time.sleep,因为您正在进行不需要的额外呼叫。

但这相当昂贵,因为您要为每次调用 main 启动一个 Python 解释器。如果我理解@BoarGules 提供的评论(尽管他的字面意思不会 运行 函数 main 并行而是顺序地执行 4 次),以下是 的替代实现main.py 的结构如下:

import sys

def main(id):
    ... # process

if __name__ == '__main__':
    main(sys.argv[1])

然后你的start.py,如果运行ning在Linux下或者一些使用fork启动新进程的平台,被编码如下:

from multiprocessing import Process
import os
import time
import main

threads = 4
id = 1
started_processes = []
for i in range(threads):
    if i != 0:
        time.sleep(5)
    p = Process(target=main.main, args=(id,))
    p.start()
    started_processes.append(p)
    id += 1
for p in started_processes:
    p.join()

但是如果你运行正在Windows下或者一些使用spawn启动新进程的平台,那么你必须编码start.py如下:

from multiprocessing import Process
import os
import time
import main

# required for Windows:
if __name__ == '__main__':
    threads = 4
    id = 1
    started_processes = []
    for i in range(threads):
        if i != 0:
            time.sleep(5)
        p = Process(target=main.main, args=(id,))
        p.start()
        started_processes.append(p)
        id += 1
    for p in started_processes:
        p.join()

并且您创建的每个新 Process 实例最终都会 运行 一个新的 Python 解释器,因此您不会比我提供的初始解决方案节省太多。

这就是为什么当您 post 用 multiprocessing 标记问题时,您也应该用平台标记问题。