专栏首页折腾折腾再折腾多任务之多进程和协程实现

多任务之多进程和协程实现

多进程

进程是什么?

上一篇我们了解了多线程,多线程实现了多任务。

那么多进程就是多任务另一种实现方式。

wondows在任务管理器中可以看到很多进程,这是我们一个程序运行之后的结果。

只有程勋运行起来才可以调度我们的资源,比如qq调用我们的摄像头。

说白了进程是操作系统分配资源的基本单位。

进程的状态

1、就绪态:条件都已经满足,等待cpu执行。

2、执行态:cpu正在执行

3、等待态:等待其他条件的满足

利用进程实现多任务

实例:

还是上一篇文章的例子:

import time

# 导入多进程模块

import multiprocessing

def movietheaters():

for i in range(3):

print('我在看电影')

time.sleep(1)

def foodGotEaten():

for i in range(3):

print('我在吃爆米花')

time.sleep(1)

def main():

# 实例一个多进程对象

p1 = multiprocessing.Process(target = movietheaters)

p2 = multiprocessing.Process(target = foodGotEaten)

# 创建一个进程

p1.start()

p2.start()

if __name__ == "__main__":

main()

这就使用进程实现了多进程。当我们start()的时候,相当于复制了一份相同的代码在子进程只是该进程只执行他该执行的代码(主语是相当于,其实不是这样,进程当然有他的优化方式,能不复制的就不复制,一般只有修改的时候才会拷贝,比线程占用的资源大)。由于主进程有的,子进程也有,占用的资源就多。效率就低了。但是在浪费资源(内存)的时候,提高了效率。

进程和线程的区别

二者的关系

现有进程才有线程,当我们把一个程序运行起来叫做进程,在一个进程里一定有一个主线程。

多线程是在一个进程里写多个线程,而多进程是多个进程里每个进程都运行一个主线程,进程多了,主线程也就多了,也就实现了多任务。通俗点相当于一个苹果2个人分,和再拿一个苹果,一人一个。当人多了,一个苹果不够分了,那就多拿几个苹果。

区别

1、线程不能独立运行,必须存在进程中。

2、使用都有自己优缺点,线程执行占用资源少,不利于资源管理和保护,同理进程相反

3、进程拥有独立的内存单元,多线程共享内存。

进程间如何传递值

上面说了,多进程是独立的内存,那怎么办?(用全局变量不行)

可以通过进程间的通讯来解决,比如socket。也可以用文件储存,一个存一个取。

但是这里不用上面的方法,我们用Queue队列(数据特性:先进先出。栈:刚好相反,先进后出)。

Queue队列是什么?

相当于一块内存,用来存数据。

如何使用:

# 导入模块

from multiprocessing import Queue

# 实例化一个队列 2表示最多放2条数据,不放数值,默认最大

q = Queue(2)

# 存放一条数据

q.put('我是第一个')

# 查看队列是否存满 是返回True,不是返回False

print(q.full())

q.put('我是第二个')

# 判断队列是否为空,是返回True,不是返回False

print(q.empty())

# 取数据

# 调用一次,只取出一个值,需要for循环取值

print(q.get())

# 当你取出一个数据的时候,队列就不是满的了

# q.qsize()返回放了多少条数据

实例实现:

import multiprocessing

def test1(queue):

list = [1,2,3,4,5]

# test1 的数据传到队列中

for item in list:

queue.put(item)

def test2(queue):

# 创建一个空列表

list2 = []

# 获取队列中的数据

while True:

if queue.empty():

break

data = queue.get()

list2.append(data)

print(list2)

def main():

# 创建队列

q = multiprocessing.Queue()

p1 = multiprocessing.Process(target = test1, args=(q,))

p2 = multiprocessing.Process(target = test2, args=(q,))

p1.start()

p2.start()

if __name__ == "__main__":

main()

这样我们就在test2中引用到了test1的数据。

进程池Pool

进程池是什么?

一个容器,能够容纳很多进程,但是能够重复运用里面的进程。

加入有10个任务,我们用进程池创建2个进程,当着两个用完,再来两个,以次类推。

什么时候进程池?

1、当不确定需要多少个进程时。

2、当需要创建的进程多的时候。

如何创建一个进程池

# 导入模块

from multiprocessing import Pool

import os,time,random

def test(m):

sta_time = time.time()

print('执行第%s个进程,进程号为:%s'%(m,os.getpid()))

time.sleep(random.random()*3)

end_time = time.time()

# 在输出的字符串前加f,{}中可以直接写参数,另一种格式化输出

print(f'执行完毕,耗时{sta_time-end_time}')

def main():

# 创建一个进程池,最大进程为3

p = Pool(3)

for i in range(10):

# 创建一个进程,第一个参数为要调度的函数,第二个为要传递的参数,为元组类型

p.apply_async(test,(i,))

print('开始进程!')

# 关闭进程池

p.close()

# 等待所有进程执行完,需要放在close后

p.join()

# 全部结束!

print('结束进程')

if __name__ == "__main__":

main()

结果:

协程

yield实现:

协程是实现多任务的第三种方式,是占用资源最少的。

还是同一个例子:

import time

# 导入多进程模块

import multiprocessing

def movietheaters():

while True:

print('我在看电影')

time.sleep(1)

yield

def foodGotEaten():

while True:

print('我在吃爆米花')

time.sleep(1)

yield

def main():

m = movietheaters()

f = foodGotEaten()

while True:

next(m)

next(f)

if __name__ == "__main__":

main()

注意:多任务分为并发和并行,并发就是假的,让你以为一时间在执行多个任务,他们只是协调了步伐,你做的时候他不做,他做你不做。并行才是同一时间执行多任务。但是往往大多数都是并发。

以上很麻烦,每次调用都需要写next()和yield

用greenlet、gevent实现多任务

greenlet实例:

首先需要安装greenlet

pip3 install greenlet

代码:

from greenlet import greenlet

import time

def movietheaters():

while True:

print('我在看电影')

gr2.switch()

time.sleep(0.5)

def foodGotEaten():

while True:

print('我在吃爆米花')

gr1.switch()

time.sleep(1)

gr1 = greenlet(movietheaters)

gr2 = greenlet(foodGotEaten)

gr1.switch()

gevent实例:

gevent只有在遇见延时的时候才会切换任务,在实际运用中不需要延时,并且延时需要gevent.sleep,不能用time.sleep。

首先需要安装gevent

pip3 install gevent

代码:

import gevent

def fun1(x):

for i in range(x):

print(f'我是fun1中的{i}')

gevent.sleep(0.5)

def fun2(x):

for i in range(x):

print(f'我是fun2中的{i}')

gevent.sleep(0.5)

g1 = gevent.spawn(fun1,10)

g2 = gevent.spawn(fun2,10)

g1.join()

g2.join()

如果我们还是想要用time.sleep(),不想用他的延时,怎么办?

需要添加一句代码:monkey.patch_all()

import gevent

import time

from gevent import monkey

monkey.patch_all()

def fun1(x):

for i in range(x):

print(f'我是fun1中的{i}')

time.sleep(0.5)

def fun2(x):

for i in range(x):

print(f'我是fun2中的{i}')

time.sleep(0.5)

g1 = gevent.spawn(fun1,10)

g2 = gevent.spawn(fun2,10)

g1.join()

g2.join()

如果我创建的多任务比较多?是不是都要写很多join?

解决:

import gevent

import time

from gevent import monkey

monkey.patch_all()

def fun1(x):

for i in range(x):

print(f'我是fun1中的{i}')

time.sleep(0.5)

def fun2(x):

for i in range(x):

print(f'我是fun2中的{i}')

time.sleep(0.5)

gevent.joinall({

gevent.spawn(fun1,10),

gevent.spawn(fun2,10),

})

注:协程中主要用gevent

进程、线程、协程对比

1、进程是资源分配的单位

2、线程是操作系统调度的单位

3、进程占用资源大

4、线程需要资源一般,效率一般

5、协程需要资源小,效率高

6、多线程和多进程根据电脑的不同,有可能是并行的,但是协程一定是并发。

本文分享自微信公众号 - python入门到放弃(python_xuexi)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python之设计模式、异常处理、模块与包、文件操作及编码

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨
  • NLP自然语言处理的开发环境搭建

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨
  • 如何让机器读懂图片上的文字?飞桨助您快速了解OCR

    OCR(Optical Character Recognition),译为光学字符识别,是指通过扫描等光学输入方式将各种票据、报刊、书籍、文稿及其它印刷品的文...

    用户1386409
  • 《Ansible自动化运维:技术与佳实践》第一章读书笔记

    Ansible 的编排引擎可以完成配置管理、流程控制、资源部署等工作。 Ansible 基于 Python语言实现,由 Paramiko 和 PyYAML 两个...

    武培轩
  • 349. 两个数组的交集

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/intersection-of-two-arrays 著...

    lucifer210
  • Beautiful Soup

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨
  • 如何教老婆快速入门Python?

    code就就是一种语言,一种计算机能读懂的语言。计算机是一个傻逼,他理解不了默认两可的任何东西。比如,你让你老公去买个西瓜,你老公会自己决定去哪里买,买几个,找...

    叫我龙总
  • Python全栈开发-常用模块学习

      模块:用来从逻辑上组织python代码(变量、函数、类、逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,模块名就是:te...

    公众号---志学Python
  • Python中turtle库的使用

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

    村雨
  • 面试官:服务器安装 JDK 还是 JRE?可以只安装 JRE 吗?

    前些日子有知友面试时被问到如题所示的问题,由于他之前没有准备到这些最最基础的知识,没有考虑过这个问题,所以被问到时竟一脸萌币,回答的不是很好。这道题主要考的是对...

    淡定的蜗牛

扫码关注云+社区

领取腾讯云代金券