python-多任务编程01-进程
Posted 马上读初一
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-多任务编程01-进程相关的知识,希望对你有一定的参考价值。
进程与程序
程序:例如xxx.py这是程序,是一个静态的
进程:一个程序运行起来后,代码+用到的资源 称之为进程,它是操作系统分配资源的基本单元。
multiprocessing模块
multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情
from multiprocessing import Process import time import os def dancing(): print(\'开始跳舞,进程号:%d\' % os.getpid()) for i in range(5): print(\'正在跳舞:。。。。%d\' % i) time.sleep(0.5) print(\'结束跳舞\') def singing(): print(\'开始唱歌,进程号:%d\' % os.getpid()) for i in range(5): print(\'正在唱歌:。。。。%d\' % i) time.sleep(0.5) print(\'结束唱歌\') if __name__ == \'__main__\': # 创建对象 p1 = Process(target=dancing) p2 = Process(target=singing) # 调用进程 p1.start() p2.start()
windows中可能多进程无效
多进程在window10下的部分IDE中运行无效,如在sublime中运行结果还是并行的
而在安装python后自带的IDLE中运行,也是无效的
而只有在cmd终端运行时并行才有效果
给进程传递参数
from multiprocessing import Process import time import os def dancing(name, num, **kwargs): print(\'开始跳舞,进程号:%d, name=%s, num=%d, age=%d\' % (os.getpid(), name, num, kwargs[\'age\'])) for i in range(num): print(\'%s正在跳舞:。。。。%d\' % (name, i)) time.sleep(0.5) print(\'结束跳舞\') def singing(name, num, **kwargs): print(\'开始唱歌,进程号:%d, name=%s, num=%d, age=%d\' % (os.getpid(), name, num, kwargs[\'age\'])) for i in range(num): print(\'%s正在唱歌:。。。。%d\' % (name, i)) time.sleep(0.5) print(\'结束唱歌\') if __name__ == \'__main__\': # 创建对象 p1 = Process(target=dancing, args=(\'xiaoming\', 5), kwargs={\'age\': 10}) p2 = Process(target=singing, args=(\'xiaohong\', 10), kwargs={\'age\': 20}) # 调用进程 p1.start() p2.start()
运行结果
进程间通信
使用multiprocessing自带的队列:Queue
from multiprocessing import Process, Queue import time def put(queue): for i in [11, 22, 33, 44, 55]: print(\'put: %d\' % i) queue.put(i) time.sleep(0.5) def read(queue): while not queue.empty(): print(\'read: %d\' % queue.get()) time.sleep(0.5) if __name__ == \'__main__\': # 创建Queue对象 queue = Queue() # 创建对象 p1 = Process(target=put, args=(queue, )) p2 = Process(target=read, args=(queue, )) # 开始进程p1 p1.start() # 等待p1运行完 p1.join() print(\'queue是否满了:\', queue.full(), \', 是否空了:\', queue.empty()) print(\'queue的大小为:%d\' % queue.qsize()) # 开始进程p2 p2.start() # 等待p2运行完 p2.join() print(\'queue是否满了:\', queue.full(), \', 是否空了:\', queue.empty()) print(\'queue的大小为:%d\' % queue.qsize())
运行结果为:
进程池
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务,
from multiprocessing import Pool import time import os import random def worker(msg): start_time = time.time() print(\'----------%s开始执行,进程号%d\' % (msg, os.getpid())) time.sleep(random.random()) end_time = time.time() print(\'----------%s执行结束, 耗时%0.2f\' % (msg, (end_time - start_time))) # 异常测试 print(\'捕获下面的print异常前\') try: print(1 + \'end\') except Exception as e: print(\'捕获到异常\') print(\'不捕获下面的print异常\') print(1 + \'end\') print(\'不捕获异常后\') def main(): # 定义进程池,最大进程数为3 pool = Pool(3) for i in range(1, 8): # 每次循环将会用空闲出来的子进程去调用目标 pool.apply_async(worker, (i, )) pool.close() pool.join() # worker(0) if __name__ == \'__main__\': main()
运行结果为:
可以看到先立马将三个进程放入进程池中并开始执行,等到其中的某个进程运行结束后,再将新的进程放入进程池中
在异常测试中发现,进程池中的方法,如果出现了异常,在运行时并不会直接报错,而只是是中断该进程,所以这里需要注意要手动将可能的异常进行捕获
进程池中使用Queue
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue(),而不是multiprocessing.Queue(),否则会得到一条如下的错误信息:
RuntimeError: Queue objects should only be shared between processes through inheritance.
进程与线程对比
定义的不同
- 进程是系统进行资源分配和调度的一个独立单位.
- 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源.
其他区别
- 一个程序至少有一个进程,一个进程至少有一个线程.
- 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高。
- 进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率
- 线程不能够独立执行,必须依存在进程中
- 线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。
以上是关于python-多任务编程01-进程的主要内容,如果未能解决你的问题,请参考以下文章