多进程
进程就是运行中的程序,而有时候处于程序运行的考虑,需要把程序变成异步执行,也就是让程序变得更加有效率。
出于系统是Windows的原因,也只是简单的学习了windows平台的多进程启动方法。multprocessing模块是python中专门为windows多进程而构建的模块。
import os
import time
from multiprocessing import Process
def func():
print('子进程:',os.getpid())
print('子进程的父进程',os.getppid())#getppid得到父进程的pid
if __name__=='__main__':#仅仅在windows上需要写
p=Process(target=func)#把函数的内存注册,所以函数的后面不加括号
#p是一个进程对象 还没有启动进程
p.start()#开启了一个子进程
time.sleep(1)
print('父进程:',os.getpid())
print('父进程的父进程',os.getppid())#getppid得到父进程的pid
需要注意的是子进程与下面的打印操作是同时进行的,并不是等子进程运行完才运行下一步,而要想等待子进程完成后在执行某些代码,需要用到join(),通常用于进程间的同步。另外也是最重要的一点,windows平台上必须要在子进程之前,加入if name=='main'。
这是 Windows 上多进程的实现问题。在 Windows 上,子进程会自动 import 启动它的这个文件,而在 import 的时候是会执行这些语句的。如果你这么写的话就会无限递归创建子进程报错。所以必须把创建子进程的部分用那个 if 判断保护起来,import 的时候 name 不是 main ,就不会递归运行了。
开启多进程的另一种方式
开启多进程还可以通过新建类并继承Process类的方法来实现,同时在实现的同时也可以通过super()方法来实现传递参数的目的,在此就不再赘述。
额外的问题
进程守护
在创建子进程时,假如使用daemon方法,那么就会把子进程变成守护进程,守护进程会随着主进程的代码执行完毕而结束,一般用来作为状态提示,注意是主进程的代码执行结束。有时候,主进程的代码执行结束后并不会关闭,假如还有别的子进程还在运行的话,所以说守护进程在主进程结束后结束是不严谨的。
from multiprocessing import Process
import time
def func():
while True:
time.sleep(0.5)
print('我还活着')
if __name__=='__main__':
p=Process(target=func)
p.daemon=True#将子进程设置为守护进程
#与主进程的代码**注意是代码,代码执行完毕后,即使主进程没有结束,它也会结束
p.start()
i=0
while i<5:
print('我是socketserver')
time.sleep(2)
i+=1
进程锁
假设有时候程序设计只允许同一时间只能有一个子进程访问文件或者修改文件,这时候就需要在在进程之前加入一道进程锁。
import json
import time
from multiprocessing import Process
from multiprocessing import Lock
def show_ticket(i):
with open('ticket','r') as f:
ticket_info=json.load(f)
print('火车站的余票有{}'.format(ticket_info['ticket']))
def buy_ticket(i,lock):
lock.acquire()
with open('ticket','r') as f:
ticket_info=json.load(f)
time.sleep(0.1)
if ticket_info['ticket']>0:
ticket_info['ticket']-=1
print('%s买到票了'%i)
else:
print('%s票卖没了'%i)
time.sleep(0.1)
with open('ticket','w') as f:
json.dump(ticket_info,f)
lock.release()
if __name__=='__main__':
for i in range(10):
p=Process(target=show_ticket,args=(i,))
p.start()
lock=Lock()
for i in range(10):
p=Process(target=buy_ticket,args=(i,lock))
p.start()
进程锁的实现需要在主进程中先定义一个进程锁lock,然后再子进程你想要加进程锁的前后加上lock.acquire()和lock.release()即可,这样就保证了同一时间只有1个进程能修改文件。
网友评论