python提供一个multiprocessing模块,取代threading来更加充分的利用CPU,避免Python全局解释器锁所带来的性能瓶颈。
创建一个进程最简单的方法是利用一个目标函数实例化一个Process对象,调用其start()使其工作。
# -*- coding:utf-8 -*-'''
@Author: 三个橘子
@Email : ipapu@qq.com
'''
import multiprocessing
'使用Process并传入一个目标函数'
def hello(name):
'''say hello'''
print('hello %s'%name)
return
if __name__=='__main__':
p1=multiprocessing.Process(target=hello,args=('joy',))
p1.start()
通过向multiprocessing.Process传递参数实例化一个p1进程,并启动这个进程,结果如下:
hello joyProcess finished with exit code 0
除了通过Process传目标函数来创建进程外,还可以通过派生来实现。
# -*- coding:utf-8 -*-'''
@Author: 三个橘子
@Email : ipapu@qq.com
'''
import multiprocessing
'派生进程'
class Hello(multiprocessing.Process):
def run(self):
print('hello world')
return
if __name__=='__main__':
p1=Hello()
p1.start()
通过派生类重写run()来实现新的工作,结果如下:
hello worldProcess finished with exit code 0
进程中还有一些其他的属性,比如:
进程id:pid
每个进程的实例都有一个对应的名称curren_process().name
有一个默认为false的daemon属性来标识是否为守护进程,当daemon值为true时进程为守护进程,即默认设置的进程都不是守护进程。守护进程会在主程序退出前自动终止。
# -*- coding:utf-8 -*-'''
@Author: 三个橘子
@Email : ipapu@qq.com
'''
import multiprocessing
import time
def hello():
process_name=multiprocessing.current_process().name
process_id=multiprocessing.current_process().pid
print("%s's id: %s"%(process_name,process_id))
def daemon():
time.sleep(3)
print('Exiting: ',multiprocessing.current_process().name,multiprocessing.current_process().pid)
if __name__=='__main__':
for i in range(3):
p=multiprocessing.Process(target=hello)
p.start()
p=multiprocessing.Process(target=daemon)
p.daemon=True
p.start() Process-1's id: 6068
Process-3's id: 7416
Process-2's id: 2288
Process finished with exit code 0
可以看到结果里面并没有daemon的输出信息。因为在其唤醒之前所有非守护进程已经退出,守护进程已经自动终止了。
如果注释掉daemon属性这一行代码,使其变为普通进程,则结果如下:
Process-3's id: 11888Process-2's id: 1336
Process-1's id: 9480
Exiting: Process-4 9316
Process finished with exit code 0
有时需要等待某一个进程完成工作并退出,可以使用它的join()方法。当调用join()之后,主程序会无限等待。所以可以通过join(i)传参的方法来设定一个期限,单位为秒数,即当超期之后即使进程尚未完成,join()也会返回。
'''接着前一个守护进程的代码'''p.join()
当守护进程调用join()后,结果:
Process-3's id: 8076Process-2's id: 12820
Process-1's id: 8032
Exiting: Process-4 13704
Process finished with exit code 0 '''接着守护进程的代码'''
p.join(1)
当守护进程调用join(1)后,结果:
Process-2's id: 1400Process-1's id: 8852
Process-3's id: 6268
Process finished with exit code 0
可以看到,未设置join参数的时候,程序会一直等到守护进程结束。但是设置时限之后,虽然主程序有等待,但是仍然在守护进程完成之前结束了程序。
有时候因为某些原因需要强制结束进程,比如当某进程陷入死锁,对一个进程对象调用terminate()会结束他的子进程。
进程的正常结束:
# -*- coding:utf-8 -*-'''
@Author: 三个橘子
@Email : ipapu@qq.com
'''
import multiprocessing
import time
def hello():
time.sleep(3)
print('hello: ', multiprocessing.current_process().name, multiprocessing.current_process().pid)
if __name__=='__main__':
p=multiprocessing.Process(target=hello)
p.start()
print('end')
当线程正常终止时结果如下:
endhello: Process-1 3004
Process finished with exit code 0
当调用terminate()强制终止:
# -*- coding:utf-8 -*-'''
@Author: 三个橘子
@Email : ipapu@qq.com
'''
import multiprocessing
import time
def hello():
time.sleep(3)
print('hello: ', multiprocessing.current_process().name, multiprocessing.current_process().pid)
if __name__=='__main__':
p=multiprocessing.Process(target=hello)
p.start()
p.terminate()
print('end') end
Process finished with exit code 0
可以明显看到程序未等到子进程正常结束就已经退出了。
如果注意的话会发现上面的程序每次输出都有一句“Process finished with exit code 0”这是什么意思呢?其实是一个进程的退出状态信息。除了code number ==0 表示没有任何错误之外,还有其他一些退出码:
>0 :进程有一个错误,并以对应的错误码推出
<0 :进程由一个 -1*exitcode信号结束