Python 多进程启动方式
1. 前言
在编写程序时,有时候需要同时执行多个任务。Python 提供了多种启动多进程的方式,本文将详细介绍这些启动方式,并给出示例代码。
2. 使用 multiprocessing
模块启动多进程
Python 的标准库中提供了 multiprocessing
模块,可以方便地启动多个子进程。它与常用的 threading
模块类似,但是能够充分利用多核 CPU 进行并行计算。
2.1. 创建子进程
使用 multiprocessing
模块,我们首先需要创建一个子进程。可以通过创建 Process
对象来实现:
import multiprocessing
def worker():
print(f"子进程 ID: {multiprocessing.current_process().pid}")
if __name__ == "__main__":
p = multiprocessing.Process(target=worker)
p.start()
p.join()
运行上述代码,会创建一个子进程并打印出子进程的 ID。Process
类的构造函数接受一个 target
参数,指定子进程要执行的函数。start()
方法启动子进程,join()
方法等待子进程执行完毕。
输出结果示例:
子进程 ID: 12345
2.2. 启动多个子进程
上述例子只启动了一个子进程,如果需要启动多个子进程,可以使用循环语句进行多次创建和启动。下面的示例代码创建了 4 个子进程,并打印出每个子进程的 ID:
import multiprocessing
def worker():
print(f"子进程 ID: {multiprocessing.current_process().pid}")
if __name__ == "__main__":
processes = []
for i in range(4):
p = multiprocessing.Process(target=worker)
processes.append(p)
p.start()
for p in processes:
p.join()
输出结果示例:
子进程 ID: 12345
子进程 ID: 12346
子进程 ID: 12347
子进程 ID: 12348
2.3. 传递参数给子进程
有时候,我们需要在主进程中定义一些数据,并将这些数据传递给子进程。可以通过在创建 Process
对象时传递参数来实现。
import multiprocessing
def worker(num):
print(f"子进程 ID: {multiprocessing.current_process().pid}")
print(f"传入的参数: {num}")
if __name__ == "__main__":
processes = []
for i in range(4):
p = multiprocessing.Process(target=worker, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join()
输出结果示例:
子进程 ID: 12345
传入的参数: 0
子进程 ID: 12346
传入的参数: 1
子进程 ID: 12347
传入的参数: 2
子进程 ID: 12348
传入的参数: 3
3. 使用 concurrent.futures
模块启动多进程
Python 3 中引入了 concurrent.futures
模块,它提供了更高级的接口,更方便地启动多个子进程。
3.1. 创建并行进程池
可以使用 concurrent.futures
模块的 ProcessPoolExecutor
类创建并行进程池。下面的示例代码创建了一个进程池并使用 submit()
方法向进程池中提交任务:
import concurrent.futures
def worker(num):
print(f"子进程 ID: {multiprocessing.current_process().pid}")
return num * 2
if __name__ == "__main__":
with concurrent.futures.ProcessPoolExecutor() as executor:
results = [executor.submit(worker, i) for i in range(4)]
for future in concurrent.futures.as_completed(results):
result = future.result()
print(f"子进程返回结果: {result}")
输出结果示例:
子进程 ID: 12345
子进程 ID: 12346
子进程 ID: 12347
子进程 ID: 12348
子进程返回结果: 0
子进程返回结果: 2
子进程返回结果: 4
子进程返回结果: 6
3.2. 使用 map()
方法启动多个子进程
ProcessPoolExecutor
类还提供了 map()
方法,可以用于启动多个子进程,并同时传递多个参数。下面的示例代码演示了如何使用 map()
方法:
import concurrent.futures
def worker(num1, num2):
print(f"子进程 ID: {multiprocessing.current_process().pid}")
return num1 + num2
if __name__ == "__main__":
with concurrent.futures.ProcessPoolExecutor() as executor:
params = [(1, 2), (3, 4), (5, 6), (7, 8)]
results = executor.map(worker, *zip(*params))
for result in results:
print(f"子进程返回结果: {result}")
输出结果示例:
子进程 ID: 12345
子进程 ID: 12346
子进程 ID: 12347
子进程 ID: 12348
子进程返回结果: 3
子进程返回结果: 7
子进程返回结果: 11
子进程返回结果: 15
4. 使用 subprocess
模块启动外部进程
除了启动 Python 子进程,我们还可以使用 subprocess
模块启动外部进程。这对于执行一些系统命令或调用其他语言编写的程序非常有用。
import subprocess
def main():
print("启动外部进程")
subprocess.run(["ls", "-l"])
print("外部进程执行完毕")
if __name__ == "__main__":
main()
运行上述代码,会在终端中执行 ls -l
命令,并将结果输出。然后打印出 “外部进程执行完毕”。
5. 总结
本文介绍了在 Python 中启动多进程的几种常用方式:使用 multiprocessing
模块创建子进程,使用 concurrent.futures
模块创建并行进程池,以及使用 subprocess
模块启动外部进程。通过灵活使用多进程,我们可以提高程序的运行效率和性能。