__init__
__new__
__str__
__len__
__del__
__eq__
__hash__
try...except...
try...except...except...
try...except...else...
finally
咱们打开任务管理器,就会发现,同一时刻用不少程序在运行。这种是的计算机能够同时处理多个任务的现象就是多任务处理。数组
有了多任务处理,咱们才能作到在听歌的同时使用QQ聊天、办公和下载文件。并发
多任务处理的几个重要概念app
程序,是一个指令的集合,也就是咱们写的一套代码。异步
进程则是指正在执行的程序。换句话说,当你运行一个程序,你就启动了一个进程。async
操做系统轮流让各个任务交替执行。因为CPU的执行速度实在是太快了,咱们感受就像全部任务都在同时执行同样。函数
多进程,就是让多个程序同时运行。多进程中,每一个进程中全部数据(包括全局变量)都各拥有一份,互不影响。测试
程序开始运行时,会首先建立一个主进程(父进程)操作系统
在主进程下,咱们能够建立新的进程,也就是子进程。code
子进程依赖于主进程,若是主进程结束,程序会退出,子进程也就自动终止。
Python提供了很是好用的多进程包multiprocessing。借助这个包,能够轻松完成单进程到并发执行的转换:
from multiprocessing import Process def land_occupation(name): print(f'{name}占领铜锣湾') def grab_the_ground(): print('抢占钵兰街') # Windows系统须要这行代码避免迭代导入的异常 if __name__ == '__main__': print('主进程启动,帮派创建') haonan = Process(target=land_occupation, args=('陈浩南',), name='陈浩南占地盘的子进程') # target表示调用的方法,args表示调用方法的位置参数元组 # 须要注意的是,若是元组只有一个元素,括号中须要加一个逗号 shisanmei = Process(target=grab_the_ground, name='十三妹抢地盘的子进程') print(haonan.name, shisanmei.name) print(haonan.pid, shisanmei.pid) haonan.start() shisanmei.start() print(haonan.pid, shisanmei.pid) haonan.join() shisanmei.join() print('程序结束') 输出的结果为: 主进程启动,帮派创建 陈浩南占地盘的子进程 十三妹抢地盘的子进程 None None 19932 19160 抢占钵兰街 陈浩南占领铜锣湾 程序结束
在上面的代码中,咱们把建立的进程和调用进程的代码都写到了if __name__ == '__main__':
的子句中。
这是由于在Windows中,子进程会自动import启动它的文件。而在import时,文件中的代码会被自动执行。当执行到建立子进程的代码时,又要从新导入本身。这就陷入了一个导入本身的死循环,而后就会报错。
为了不报错,咱们把这些代码放到if __name__ == '__main__':
的子句中,这样当建立子进程时,导入代码就不会从新加载建立子进程的语句了。
不过最好仍是将操做多进程的代码封装到函数中,这样会避免不少麻烦。
Process(target, name, args)
参数介绍
Process类经常使用方法
.start()
:启动进程,并调用子进程中的.run()
方法.run()
:进程启动时调用的方法,正是它去调用target参数指定的函数。.terminate()
:(了解便可)强制终止进程,不会进行任何清理操做,进程会一直占用内存空间.is_alive()
:若是进程仍在运行,返回True,不然返回False。用来判断进程是否还在运行.join([timeout])
:中近程等待子进程终止,timeout时可选的超时时间Process类经常使用属性:
全局变量在多个进程中是不共享的。进程之间的数据相互独立,默认状况下不会相互影响:
from multiprocessing import Process num = 10 def r1(): global num num += 5 print('在进程一中,num的值为:', num) def r2(): global num num += 10 print('在进程二中,num的值为:', num) if __name__ == '__main__': p1 = Process(target=r1) p2 = Process(target=r2) p1.start() p2.start() p1.join() p2.join() print('程序结束前,主进程中num的值为:', num) 输出的结果为: 在进程一中,num的值为: 15 在进程二中,num的值为: 20 程序结束前,主进程中num的值为: 10
须要注意的是,每次建立进程对象时,都会import当前文件。这就致使在if __name__ == '__main__'
语句以后对num进行的修改操做不会被加载到进程对象的内存中。换句话说,子进程可以加载全局变量在if __name__ == '__main__'
语句以外的修改,却没法加载其内部的修改:
from multiprocessing import Process num = 10 def r1(): global num num += 5 print('在进程一中,num的值为:', num) def r2(): global num num += 10 print('在进程二中,num的值为:', num) # 在外部修改全局变量num num += 500 if __name__ == '__main__': # 在内部修改全局变量 num += 1000 p1 = Process(target=r1) p2 = Process(target=r2) p1.start() p2.start() p1.join() p2.join() print('程序结束前,主进程中num的值为:', num) 输出的结果为: 在进程一中,num的值为: 515 在进程二中,num的值为: 520 程序结束前,主进程中num的值为: 1510
在子进程中,1000都没有被加上,可是500被加上了。由此能够验证前面的观点。
除了直接使用Process建立类对象以外,咱们还能够本身写进程对象,只需继承Process类便可:
from multiprocessing import Process import time class ClockProcess(Process): # 重写的run方法就是咱们要执行的子进程方法 def run(self): n = 5 while n > 0: print(n) time.sleep(1) n -= 1 if __name__ = '__main__': p = ClockProcess() p.start() p.join() 输出的结果为: 5 4 3 2 1 上面的内容每隔一秒钟打印出一个
进程池用来建立多个进程。
当须要建立的子进程数量很少时,能够直接利用multiprocessing中的Process动态生成多个进程。但若是咱们须要建立大量的进程,若是手动建立那工做量将极其巨大。并且会产生不少的重复代码。此时,就能够用到multiprocessing模块提供的Pool来实现批量建立多个进程。
初始化Pool时,能够指定一个最大进程数。当有新的请求提交到Pool中时,若是池尚未满,那么就会建立一个新的进程用来执行该请求;若是池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会建立新的进程来执行。
建立进程池的基本办法为:
from multiprocessing import Pool import time def r1(): print('这里是进程一呀~') time.sleep(5) def r2(): print('这里是进程二呀~') time.sleep(3) if __name__ == '__main__': # 定义一个进程池,参数为最大进程数,默认大小为CPU核数 po = Pool() for i in range(100): # apply_async选择要调用的目标,每次循环会用空出来的子进程去调用目标 po.apply_async(r1) po.apply_async(r2) # 进程池关闭后再也不接收新的请求 po.close() # 等待po中全部子进程结束,必须放在close后面 po.join() # 在多进程中,主进程通常用来等待,真正的任务都在子进程中
multiprocessing.Pool
经常使用函数解析
apply_async(func[, args[, kwargs]])
:使用非阻塞方式调用func(并行执行,阻塞方式必须等待上一个进程退出才能执行下一个进程)。args为传递给func的位置参数,kwargs为传递给func 的关键字参数apply(func[, args[, kwargs]])
(了解便可)使用阻塞方式调用func,效果与单进程相同close()
:关闭进程池,使其再也不接收新的任务join()
:主进程阻塞,等待子进程的退出,必须在close或terminate以后使用