Python 多进程

5 投票
3 回答
2676 浏览
提问于 2025-04-16 20:04

这个问题主要是想了解一些事实和思路,而不是具体的代码。

我有很多编译好的C++程序,需要在不同的时间和用不同的参数来运行它们。我在考虑使用Python的多进程功能,从任务队列(rabbitmq)中读取任务,然后把这个任务交给一个C++程序去执行(可能是用子进程)。我选择多进程模块是因为我的服务器是双Xeon的,所以我想充分利用服务器的多处理器能力。

这个Python程序会充当中央管理者,简单地从队列中读取任务,启动一个进程(或者子进程?)来运行相应的C++程序,获取结果(子进程的标准输出和错误输出),把这些结果传给一个回调函数,然后把这个进程放回等待下一个任务的进程队列中。

首先,这听起来像是一个有效的策略吗?

其次,有没有类似的例子可以参考?

提前谢谢你。

3 个回答

0

听起来这个策略不错,但其实你不需要用到 multiprocessing 模块,而是应该用 subprocess 模块。subprocess 是用来从 Python 程序中运行子进程并与它们进行交互的(比如输入输出、管道等),而 multiprocessing 更侧重于把 Python 代码 分配到多个进程中去运行,以通过并行处理来提高性能。

根据你的响应策略,你可能还想看看 threading 模块,它可以让你从一个线程中启动子进程。这样,你就可以在等待一个子进程的同时,仍然能保持响应,接受其他任务。

1

首先,这听起来像是一个有效的策略吗?

是的。

其次,有没有类似的例子可以参考?

Celery

11

这个Python程序会作为中央管理者,简单地从任务队列中读取工作,然后启动一个进程(或者说子进程?),用合适的C++程序来执行这个工作,获取结果(子进程的标准输出和错误输出),把这些结果传给一个回调函数,然后把这个进程放回等待下一个工作的进程队列中。

你不需要使用multiprocessing模块。multiprocessing模块适合用来将Python函数作为独立的进程运行。如果你只是想运行一个C++程序并读取标准输出的结果,使用subprocess模块就足够了。队列可以用一个列表来表示,你的Python程序只需要在列表不为空的时候循环执行。


不过,如果你想要:

  1. 启动多个工作进程
  2. 让它们从一个公共的队列中读取任务
  3. 使用队列中的参数来并行启动C++程序
  4. 用C++程序的输出结果来添加新的任务到队列中

那么你可以像这样使用multiprocessing

test.py:

import multiprocessing as mp
import subprocess
import shlex

def worker(q):
    while True:
        # Get an argument from the queue
        x=q.get()

        # You might change this to run your C++ program
        proc=subprocess.Popen(
            shlex.split('test2.py {x}'.format(x=x)),stdout=subprocess.PIPE)
        out,err=proc.communicate()

        print('{name}: using argument {x} outputs {o}'.format(
            x=x,name=mp.current_process().name,o=out))

        q.task_done()

        # Put a new argument into the queue
        q.put(int(out))

def main():
    q=mp.JoinableQueue()

    # Put some initial values into the queue
    for t in range(1,3):
        q.put(t)

    # Create and start a pool of worker processes
    for i in range(3):
        p=mp.Process(target=worker, args=(q,))
        p.daemon=True
        p.start()
    q.join()
    print "Finished!"

if __name__=='__main__':
    main()

test2.py(这是你C++程序的一个简单替代品):

import time
import sys

x=int(sys.argv[1])
time.sleep(0.5)
print(x+3)

运行test.py可能会得到类似这样的结果:

Process-1: using argument 1 outputs 4
Process-3: using argument 3 outputs 6
Process-2: using argument 2 outputs 5
Process-3: using argument 6 outputs 9
Process-1: using argument 4 outputs 7
Process-2: using argument 5 outputs 8
Process-3: using argument 9 outputs 12
Process-1: using argument 7 outputs 10
Process-2: using argument 8 outputs 11
Process-1: using argument 10 outputs 13

注意右侧列的数字会被反馈回队列,并最终作为参数传递给test2.py,在左侧列中显示为数字。

撰写回答