一、多进程实现
1.用进程池方法:
例子:假设有两个任务:run_proc()、long_time_task()需要并行执行。
# encoding = utf8
from multiprocessing import Process,Queue,Pool
import os, time, random
def run_proc():
"""第一个进程"""
print("第一个进程开始")
time.sleep(10)
print('第一个进程结束')
def long_time_task():
"""第二个进程"""
print("第二个进程开始")
time.sleep(10)
print('第二个进程结束Run task (%s)...' % (os.getpid()))
def mul_run():
"""多进程方式运行任务"""
start = time.time()
p = Pool(2)
for L in [run_proc, long_time_task]:
p.apply_async(L, args=())
p.close()
"""对Pool对象调用join()方法会等待所有子进程执行完毕,
调用join()之前必须先调用close(),
调用close()之后就不能继续添加新的Process了"""
p.join()
end = time.time()
print("多进程执行时间: ", end -start)
def run():
"""不用多进程执行时间"""
start = time.time()
run_proc()
long_time_task()
end = time.time()
print("单进程执行时间: ", end -start)
if __name__=='__main__':
mul_run()
run()
执行结果:
E:\soft\python3\python.exe C:/Users/Lenovo/PycharmProjects/matplot_graph/Dict.py
第一个进程开始
第二个进程开始
第一个进程结束
第二个进程结束Run task (18544)...
多进程执行时间: 10.208519697189331
第一个进程开始
第一个进程结束
第二个进程开始
第二个进程结束Run task (4124)...
单进程执行时间: 20.00142812728882
Process finished with exit code 0
2、普通方式
# encoding = utf8
from multiprocessing import Process,Queue,Pool
import os, time, random
def run_proc():
"""第一个进程"""
print("第一个进程开始")
time.sleep(10)
print('第一个进程结束')
def long_time_task():
"""第二个进程"""
print("第二个进程开始")
time.sleep(10)
print('第二个进程结束Run task (%s)...' % (os.getpid()))
def mul_run():
"""多进程方式运行任务"""
proList = []
start = time.time()
for L in [run_proc, long_time_task]:
p = Process(target=L, args=())
proList.append(p)
"""保证进程同时进行"""
for t in proList:
t.start()
"""保证进程都结束"""
for t in proList:
t.join()
end = time.time()
print("多进程执行时间: ", end -start)
def run():
start = time.time()
run_proc()
long_time_task()
end = time.time()
print("单进程执行时间: ", end -start)
if __name__=='__main__':
mul_run()
run()
执行结果:
E:\soft\python3\python.exe C:/Users/Lenovo/PycharmProjects/matplot_graph/Dict.py
第一个进程开始
第二个进程开始
第一个进程结束
第二个进程结束Run task (11652)...
多进程执行时间: 10.093430280685425
第一个进程开始
第一个进程结束
第二个进程开始
第二个进程结束Run task (6444)...
单进程执行时间: 20.00089693069458
Process finished with exit code 0
二、让python执行命令行
1、子进程方式
subprocess
模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。下面的例子演示了如何在Python代码中运行命令“pip”,这和命令行直接运行的效果是一样的:
import subprocess
p = subprocess.Popen(['pip'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
print(output.decode('gb2312'))
print('Exit code:', p.returncode)
如果子进程还需要输入,则可以通过communicate()
方法输入。
2、如果不想传参数,且希望得到返回值。用:os.popen()
import os
strList = os.popen("pip").readlines()
print strList
3.如果仅仅是执行,不传参,也不想得到返回值,用os.system()
os.system("cd /home/map/opt/lstm-name-comp;rm " + fileName)
三、进程间通信
1、Queue方式:
Put方法:以插入数据到队列中,他还有两个可选参数:blocked和timeout。详情自行百度
Get方法:从队列读取并且删除一个元素。同样,他还有两个可选参数:blocked和timeout。详情自行百度
from multiprocessing import Process, Queue
import os, time, random
def proc_write(q,urls):
print('Process is write %s' % os.getpid())
for url in urls:
q.put(url)
print('put %s to queue... ' %url)
time.sleep(1)
def proc_read(q):
print('Process is reading %s' % os.getpid())
while True:
url = q.get(True)
print('Get %s from queue' %url)
def multi_pro():
w_list = []
r_list = []
q = Queue()
proc_write1 = Process(target=proc_write, args=(q, ['url_1', 'url_2', 'url_3']))
w_list.append(proc_write1)
proc_write2 = Process(target=proc_write, args=(q, ['url_4', 'url_5', 'url_6']))
w_list.append(proc_write2)
proc_reader = Process(target=proc_read, args=(q,))
r_list.append(proc_reader)
"""启动读写进程"""
for L in w_list + r_list:
L.start()
"""等待写进程结束"""
for L in w_list:
L.join()
"""关闭读进程"""
for L in r_list:
L.terminate()
if __name__ == '__main__':
multi_pro()
2、Pip管道方式:
(1)Pipe常用于两个进程,两个进程分别位于管道的两端
(2)Pipe方法返回(conn1,conn2)代表一个管道的两个端,Pipe方法有duplex参数,默认为True,即全双工模式,若为FALSE,conn1只负责接收信息,conn2负责发送,
import multiprocessing
import os,time,random
def proc_send(pipe,urls):
for url in urls:
pipe.send(url)
time.sleep(random.random())
def proc_recv(pipe):
while True:
print('Process rev:%s' %pipe.recv())
time.sleep(random.random())
if __name__ == '__main__':
pipe = multiprocessing.Pipe()
p1 = multiprocessing.Process(target=proc_send,args=(pipe[0],['url_'+str(i) for i in range(10) ]))
p2 = multiprocessing.Process(target=proc_recv,args=(pipe[1],))
p1.start()
p2.start()
p1.join()
p2.terminate()
总结:队列方式优点是不限进程个数。缺点是不能全双工。
管道方式可以全双工,但是只能两个两个进程通信。