Python程序实现多进程(multiprocessing)
Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。
进程 multiprocessing
示例代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 进程调用
from multiprocessing import Process
import os
def run_proc(name):
print("运行子进程 %s (%s)" % (name, os.getpid()))
if __name__ == "__main__":
print("父进程 %s" % (os.getpid()))
# 调用子进程函数
p = Process(target = run_proc, args = ("test", ))
print("子进程, 即将启动")
p.start()
p.join()
print("子进程,调用结束")
运行结果
D:\PythonProject>python main.py
父进程 4552
子进程, 即将启动
运行子进程 test (5632)
子进程,调用结束
线程池 Pool
运行示例
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 线程池 Pool 批量创建子进程
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print("运行子进程 %s (%s)"%(name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print("子进程 %s 运行 %0.2f 秒." % (name, (end-start)))
if __name__ == "__main__":
print("父进程为 %s" % os.getpid())
# 线程池,最多同时运行4个进程
p = Pool(4)
# 批量产生 5 个 进程
for i in range(5):
# 调用子进程函数
p.apply_async(long_time_task, args=(i,))
print("等待所有子进程完成")
p.close()
p.join()
print("所有子进程运行完毕")
运行结果
D:\PythonProject>python main.py
父进程为 8536
等待所有子进程完成
运行子进程 0 (808)
运行子进程 1 (2728)
运行子进程 2 (7876)
运行子进程 3 (3872)
子进程 3 运行 0.59 秒.
运行子进程 4 (3872)
子进程 2 运行 1.10 秒.
子进程 0 运行 1.59 秒.
子进程 1 运行 1.87 秒.
子进程 4 运行 2.57 秒.
所有子进程运行完毕
进程间通信
示例代码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# 进程间通信
# multiprocessing 模块包装了底层的机制,提供了Queue,Pipes等多种方式交换数据
from multiprocessing import Process, Queue
import os, time, random
# 写数据进程执行的代码
def write(q):
print("进程 %s 写数据" % os.getpid())
for value in [1,2,3]:
print("数据 %d 写入队列中..." % value)
q.put(value)
time.sleep(random.random())
# 读数据进程执行的代码
def read(q):
print("进程 %s 读数据" % os.getpid())
while True:
value = q.get(True)
print("读出来的数据是 %d" % value)
if __name__ == "__main__":
# 父进程创建Queue,并传给各个子进程
q = Queue()
# 启动子进程 pw,写入
pw = Process(target = write, args = (q,))
pw.start()
# 启动子进程 pr, 读取
pr = Process(target = read, args = (q,))
pr.start()
# 等待 pw 结束
pw.join()
# pr 是无限循环,强行终止
pr.terminate()
运行结果
D:\PythonProject>python main.py
进程 9032 写数据
数据 1 写入队列中...
进程 3808 读数据
读出来的数据是 1
数据 2 写入队列中...
读出来的数据是 2
数据 3 写入队列中...
读出来的数据是 3