注:如果未加入#coding:gbk
或者#coding:utf-8
,运行程序可能会报SyntaxError: Non-UTF-8 code starting with
错误.
python创建子进程
其中可以通过Process来构造一个子进程
p = Process(target=fun,args=(args))
再通过p.start()来启动子进程
再通过p.join()方法来使得子进程运行结束后再执行父进程
#coding:gbk
from multiprocessing import Process
import os
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__ == '__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Process will start.')
p.start()
p.join()
print('Process end.')
python利用进程池管理子进程
其中p.close()用来关闭进程池,进程池关闭后,就不能调用apply_async方法增加新的进程了。(一个池子里能同时运行多少个进程,取决于电脑cpu的数量,如果下面的代码中p=Pool(5)那么所有的子进程就可以同时进行,具体原因后续再研究)
#coding:gbk
from multiprocessing import Pool
import os, time
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__ == '__main__':
print('Parent process %s.' % os.getpid())
p = Pool()
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
多个子进程间的通信用队列通信
队列中可以放任意格式的数据,实现多个子进程之间的通信,但是子进程跟父进程之间的通信需要使用multiprocess的Manager类 后面讲
#coding:gbk
from multiprocessing import Process, Queue
import os, time, random
# 写数据进程执行的代码:
def write(q):
for value in ['A', 'B', 'C']:
print ('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
# 读数据进程执行的代码:
def read(q):
while True:
if not q.empty():
value = q.get(True)
print('Get %s from queue.' % value)
time.sleep(random.random())
else:
break
if __name__== '__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 等待pw结束:
pw.join()
# 启动子进程pr,读取:
pr.start()
pr.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
print('所有数据都写入并且读完')
使用multiprocess的Manager类实现子进程与父进程之间的通信,以及多个子进程之间使用进程池的情况下通信也需使用multiprocess的Manager类
声明队列时使用manager.Queue()
声明队列。(注意 读取的数据不一定完全,因为有的数据还未写入,读取任务就开始运行了)
# 将上面的代码main函数替换掉
if __name__ == '__main__':
manager = multiprocessing.Manager()
q = manager.Queue()
p = Pool()
pw = p.apply_async(write, args=(q,))
time.sleep(0.5)
pr = p.apply_async(read, args=(q,))
p.close()
p.join()
print('数据读取完成')
可以利用进程锁,锁定同时只有一个进程对队列的值进行更改
使用lock = manager.Lock()
声明一个锁,再进程执行的时候,将锁传入进程,可实现对队列的加锁和释放锁。
from multiprocessing import Process, Queue, Pool
import multiprocessing
import os, time, random
def write1(q, lock):
lock.acquire() # 加上锁
for value in ['A', 'B', 'C']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
lock.release()
def write2(q, lock):
lock.acquire() # 加上锁
for value in ['D', 'E', 'F']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
lock.release()
if __name__ == '__main__':
q = Queue()
manager = multiprocessing.Manager()
lock = manager.Lock()
pw1 = Process(target=write1, args=(q, lock))
pw2 = Process(target=write2, args=(q, lock))
# 启动子进程pw,写入:
pw1.start()
pw2.start()
# pr.start()
pw1.join()
pw2.join()
# pr.join()
print('所有数据都写入并且读完')