小能豆

在后台将模块作为子进程启动,然后分离

py

在 中bash,我可以执行以下操作:

for f in subdir/*.sh; do
    nohup "$f" "$@" &> /dev/null &
done

换句话说,它在后台运行所有*.sh脚本,并且分离,这样如果主脚本结束,后台脚本就不会终止。subdir

现在,假设我有以下 Python 项目:

proj/
    __init__.py
    main.py
    subdir/
        __init__.py
        mod_a.py
        mod_b.py
        mod_c.py

我该如何做类似 bash 脚本的事情?但参数要以 Python 对象的形式传递?

例如:我有两个字符串ab,一个列表l和一个字典d

  • 加载mod_a.py、调用mod_a.main(a, b, l, d)和分离
  • 加载mod_b.py、调用mod_b.main(a, b, l, d)和分离
  • 加载mod_c.py、调用mod_c.main(a, b, l, d)和分离
  • main.py可以结束,让mod_amod_bmod_c在后台运行,直到完成

阅读 23

收藏
2024-12-04

共1个答案

小能豆

在 Python 中,你可以使用 multiprocessingthreading 模块来实现类似于 Bash 脚本中的后台运行任务。不过,由于 Python 是单线程的,因此如果你想要并行执行多个脚本并且让它们在主脚本结束时继续执行,可以使用 multiprocessing 来实现后台执行。

下面是一个使用 multiprocessing 模块的示例,它能够在后台并行执行多个模块(mod_a.py, mod_b.py, mod_c.py)中的 main() 函数:

1. 使用 multiprocessing 实现并行执行模块:

项目结构:

proj/
    __init__.py
    main.py
    subdir/
        __init__.py
        mod_a.py
        mod_b.py
        mod_c.py

main.py 示例:

import multiprocessing
import importlib
import sys

# 加载并调用模块的函数
def run_module(module_name, a, b, l, d):
    # 动态加载模块
    mod = importlib.import_module(f"subdir.{module_name}")
    # 调用模块中的 main 函数
    mod.main(a, b, l, d)

if __name__ == "__main__":
    # 假设这些是你传递给各个模块的参数
    a = "example_a"
    b = "example_b"
    l = [1, 2, 3]
    d = {"key1": "value1", "key2": "value2"}

    # 使用 multiprocessing 来启动后台任务
    processes = []
    modules = ['mod_a', 'mod_b', 'mod_c']  # 模块列表

    for module in modules:
        # 创建一个进程来运行模块的 main 函数
        p = multiprocessing.Process(target=run_module, args=(module, a, b, l, d))
        p.start()  # 启动进程
        processes.append(p)

    # 等待所有后台进程完成
    for p in processes:
        p.join()  # 等待每个进程结束

subdir/mod_a.py 示例:

def main(a, b, l, d):
    # 你的代码逻辑
    print(f"mod_a received: a={a}, b={b}, l={l}, d={d}")

subdir/mod_b.py 示例:

def main(a, b, l, d):
    # 你的代码逻辑
    print(f"mod_b received: a={a}, b={b}, l={l}, d={d}")

subdir/mod_c.py 示例:

def main(a, b, l, d):
    # 你的代码逻辑
    print(f"mod_c received: a={a}, b={b}, l={l}, d={d}")

解释:

  1. multiprocessing 模块: 使用 multiprocessing 可以让你在后台启动多个进程并行运行多个任务,而主程序本身不会被阻塞。
  2. importlib.import_module 用于动态加载指定模块,可以在运行时加载 mod_a.pymod_b.pymod_c.py 等模块。
  3. Process 类: 每个进程都会执行模块的 main() 函数,在后台独立运行,这样可以实现你想要的“后台执行”的效果。
  4. join() 方法: 在主进程中调用 join() 来等待每个子进程完成。如果你不调用 join(),主进程会在子进程执行时直接结束,导致子进程可能没有完成就退出了。

结果:

  • main.py 作为主程序,在启动后会并行执行 mod_a.main(), mod_b.main(), mod_c.main(),并将参数 a, b, l, d 传递给每个模块。
  • 主程序可以结束,但后台的 mod_a, mod_b, mod_c 会继续运行直到完成。

附加说明:

  • 分离进程: multiprocessing 会创建新的进程,这些进程是独立的,不会影响主进程的生命周期。如果你希望进程在主程序退出后继续运行,可以将 daemon=True 传递给 Process,但在大多数情况下,不需要这样做,因为 multiprocessing 会确保进程的独立性。
  • 进程管理: 如果你希望能够管理这些后台进程,可以使用进程池(Pool)或进程队列来处理进程间的通信和任务分配。
2024-12-04