版权声明:由于作者水平有限,文中难免有误,欢迎各位业界同仁斧正! https://blog.csdn.net/UserPython/article/details/82463519
multiprocessing 多进程
多进程的创建及使用
import multiprocessing, time
def run(name):
time.sleep(2)
print("hello", name)
if __name__ == "__main__":
for i in range(10):
p = multiprocessing.Process(target = run, args = ("UserH %s" % i, )) #创建进程
p.start()
每一个进程都是由父进程启动的,所以每个进程都有一个父进程
from multiprocessing import Process
import os
def run():
#每个进程都是由副进程启动的,每个进程都有一个副进程
print("Parent process:", os.getppid()) #返回父进程id
print("Process id:", os.getpid()) #返回当前进程id
if __name__ == "__main__":
run()
from multiprocessing import Process
import os
def info(title):
print(title)
print("module name:", __name__)
#每个进程都是由副进程启动的,每个进程都有一个副进程
print("Parent process:", os.getppid()) #返回父进程id
print("Process id:", os.getpid()) #返回当前进程id
print("\n\n") #空两行
def fun(name):
info("called from child process function") #在子进程又调用info
print("hello", name)
if __name__ == "__main__":
info("--main process line--") #主程序调用info
p = Process(target = fun, args = ("UserH", ))
p.start()
#-----------------------------------------------------------
--main process line--
module name: __main__
Parent process: 11752
Process id: 3560
called from child process function
module name: __mp_main__
Parent process: 3560 ----------》子进程与父进程的PID一样,说明当前的子进程由父进程启动
Process id: 8892
hello UserH
进程间通信
不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用一下的方法:
Queue
from multiprocessing import Process, Queue
def fun(qq):
qq.put([42, None, "hello"])
if __name__ == "__main__":
q = Queue()
p = Process(target = fun, args = (q, ))
p.start()
print(q.get())
p.join()
Pipe
from multiprocessing import Process, Pipe
def fun(conn):
conn.send([42, None, "hello"])
conn.close()
if __name__ == "__main__":
parent_conn, child_conn = Pipe() #生成一个管道实例,就会产生两个返回对象
p = Process(target = fun, args = (child_conn, ))
p.start()
print(parent_conn.recv()) #接收消息
p.join()
Manager
运行的结果中字典的多个线程中,出现重复数据证明了多进程的共享
from multiprocessing import Process, Manager
import os
def fun(d, l): #字典开始是一个空字典
d[os.getpid()] = os.getpid()
#每个列表里面都放了当前PID
l.append(os.getpid())
print(l)
if __name__ == "__main__":
with Manager() as manager:
d = manager.dict() #生成一个字典,可在多个进程间共享和传递
l = manager.list(range(5))#生成一个列表,默认有五个数字,可在多个进程间共享和传递
p_list = []
for i in range(5):
p = Process(target = fun, args = (d, l))
p.start()
p_list.append(p)
for res in p_list: #等待结果
res.join()
print(d)
print(l)
#----------------------------------------------------
[0, 1, 2, 3, 4, 600]
[0, 1, 2, 3, 4, 600, 12680]
[0, 1, 2, 3, 4, 600, 12680, 1584]
[0, 1, 2, 3, 4, 600, 12680, 1584, 10060]
[0, 1, 2, 3, 4, 600, 12680, 1584, 10060, 604]
{600: 600, 12680: 12680, 1584: 1584, 10060: 10060, 604: 604}
[0, 1, 2, 3, 4, 600, 12680, 1584, 10060, 604]
线程同步—进程锁Lock
from multiprocessing import Process, Lock
def fun(l, i):
l.acquire()
try:
print("hello world", i)
finally:
l.release()
if __name__ == "__main__":
lock = Lock()
for num in range(10):
Process(target = fun, args = (lock, num)).start()
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,知道进程池中有可用进程为止
进程池中有两个方法:apply (串行), apply_async(并行)
from multiprocessing import Process, Pool
import time
import os
def foo(i):
time.sleep(2)
print("in process:", os.getpid())
return i + 100
def bar(arg):
print("--->exec done:", arg, os.getpid()) #回调是主进程执行调用
if __name__ == "__main__":
pool = Pool(5) #允许进程池同时放入5个进程
print("主进程PID:", os.getpid())
for i in range(10):
pool.apply_async(func = foo, args = (i, ), callback = bar) #callback = 回调,意思是先执行完foo,再执行bar,干不完foo,则不执行bar
# pool.apply(func = foo, args = (i, )) #串行
# pool.apply_async(func = foo, args = (i, )) #并行
print("end")
pool.close()
pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭