协程

python-使用协程下载妹子图片

流过昼夜 提交于 2019-12-03 04:10:29
import urllib.requestimport geventimport gevent.monkeygevent.monkey.patch_all()def downloader(img_name, img_url): req = urllib.request.urlopen(url=img_url) img_content = req.read() with open(img_name, 'wb') as f: f.write(img_content)def main(): gevent.joinall([gevent.spawn(downloader, '1.jpg', 'https://rpic.douyucdn.cn/live-cover/roomCover/2019/09/05/6668ef0693e932a3fec8994d8bfdcbaf_big.jpg'), gevent.spawn(downloader, '2.jpg', 'https://rpic.douyucdn.cn/live-cover/appCovers/2019/10/19/7605123_20191019184322_small.jpg') ])if __name__ == '__main__': main() 来源: https://www.cnblogs.com/fuyouqiang/p

python-协程gevent的使用

白昼怎懂夜的黑 提交于 2019-12-03 03:56:27
import geventfrom gevent import monkeyimport timeimport random# 有耗时操作时需要monkey.patch_all() # 将程序中用到的耗时操作代码,换为 gevent 中自己实现的模块def work(name): for i in range(10): print(name, i) time.sleep(random.random())gevent.joinall([ gevent.spawn(work, 'work1'), gevent.spawn(work, 'work2')])# 等价于'''g1 = gevent.spawn(work, 'work1')g2 = gevent.spawn(work, 'work2')g1.join()g2.join()''' 来源: https://www.cnblogs.com/fuyouqiang/p/11775772.html

Python迭代器,生成器和协程

一曲冷凌霜 提交于 2019-12-03 03:24:19
Python迭代器,生成器和协程 基础概念 在学习Python协程之前首先需要了解Python生成器的概念,而生成器又是一种特殊的迭代器,所以从迭代器开始学习。 Python迭代器(Iterator) 首先了解可迭代对象(interable), 具体来说就是遵循了可迭代协议的对象,比如查看Python list内置类的源码可以发现它实现了 iter ()函数,所以list是一个可迭代对象,当然还有dict, str, set等等。 可迭代协议:含 iter ()方法。且可迭代对象中的 iter ()方法返回的是一个对应的迭代器。(如list对应的迭代器就是list_iterator) 而迭代器与可迭代对象不同的是,迭代器对象不仅需要实现 iter ()方法,它还需要实现 next ()方法,即迭代器协议,事实上任何实现了 iter ()和 next ()方法的类对象都可以是迭代器对象。 迭代器协议: - 含 iter ()方法。且方法返回的Iterator对象本身 - 含 next ()方法,每当 next ()方法被调用,返回下一个值,直到没有值可以访问,这个时候会抛出stopinteration的异常。 此外迭代器含有两个基本的方法iter()和next(), iter()方法的作用是返回一个迭代器对象,当我们使用迭代器的next()方法显式获取元素的时候

Python之路(第四十七篇) 协程

此生再无相见时 提交于 2019-12-03 02:45:09
一、协程介绍 协程:是单线程下的并发,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程: 协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。 协程相比于线程,最大的区别在于,协程不需要像线程那样来回的中断切换,也不需要线程的锁机制,因为线程中断或者锁机制都会对性能问题造成影响,所以协程的性能相比于线程,性能有明显的提高,尤其在线程越多的时候,优势越明显。 协程的好处: 无需线程上下文切换的开销 无需原子操作锁定及同步的开销 "原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。 方便切换控制流,简化编程模型 高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。 缺点: 无法利用多核资源:协程的本质是个单线程,它不能同时将单个 CPU 的多个核用上,协程需要和进程配合才能运行在多 CPU 上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是 CPU 集型应用。 进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序

通道(channel)

折月煮酒 提交于 2019-12-03 02:05:30
描述 主要用于多个goroutine间传递数据.一个通道相当于一个先进先出(FIFO)的队列. channel用来在协程[goroutine]之前传递数据,准确的说,是用来传递数据的所有权。 一个设计良好的程序应该确保同一时刻channel里面的数据只会被同一个协程拥有,这样就可以避免并发带来的数据不安全问题[data races]。 官方的go编译器限制channel最多能容纳到65535个元素,但我们不宜传递体积过大的元素值,因为channel的数据 从进入到流出会涉及到数据拷贝操作 。如果 元素 体积过大,最好的方法还是使用传递指针来取代传递值。 内部结构 每个channel内部实现都有三个队列。 接收消息的协程队列。 这个队列的结构是一个限定最大长度的链表,所有阻塞在channel的接收操作的协程都会被放在这个队列里。 发送消息的协程队列。 这个队列的结构也是一个限定最大长度的链表。所有阻塞在channel的发送操作的协程也都会被放在这个队列里。 环形数据缓冲队列。 这个环形数组的大小就是channel的容量。如果数组装满了,就表示channel满了,如果数组里一个值也没有,就表示channel是空的。 对于一个阻塞型channel来说,它总是同时处于即满又空的状态。一个channel被所有使用它的协程所引用,也就是说,只要这两个装了协程的队列长度大于零

进程,线程,协程

匿名 (未验证) 提交于 2019-12-03 00:36:02
cpu:内核 进程: 优点:提高效率,利用cpu多核优势 开启个数:理论上是cpu内核的1-2倍 描述:一段程序或者脚本的执行,cpu资源分配的最小单位 缺点:资源消耗非常大,进程过多,cpu切换进程执行也消耗资源,资源共享困难 使用场景:cpu密集型应用程序(计算密集型) 线程: 优点:提高效率,资源共享 开启个数:跟计算硬件有关系,跟应用场景有关系,一般高于可开启进程守数 描述:进程下可以开启多个线程,cpu调度的最小单位 缺点:开启个数也不是无限的,如果开启过多,造成进程瘫痪 使用场景:IO(input(response),ouput(request),)密集型应用程序,爬虫成是网络IO,长延时操作 跨平台的进程创建模块(multiprocessing) multiprocessing模块提供了一个Process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束 步骤: 1、从multiprocessing模块导入Process类 2、进程的操作(1)创建和启动创建子进程时,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start()方法启动,这样创建进程比fork()还要简单。创建格式:p=Process(target=函数名)启动格式:进程对象名.start() 参数列表:Process([group [, target [, name

libco协程库原理解析与应用

匿名 (未验证) 提交于 2019-12-03 00:26:01
最近在准备一个libco协程库原理简析与应用的分享,顺便就整理下写个博客,一方面加深下自己对协程库的理解,另一方面也希望能对想了解协程的学者有所帮助。废话不多说了,言归正传吧。 想去剖析libco协程库的实现原理,首先我们要了解下什么是协程。维基百科上给协程的定义是协程(coroutine)又称微线程,是一个无优先级的子程序(函数)调度组件,允许子程序在特定的地方挂起和恢复。我们可通过一个例子来理解下这句话的意思。函数调用大家都很熟悉吧,下面的这个是一个函数调用的例子。 我们可以很容易的看出函数执行的结果是1 2 3 x y z。而协程的定义说是函数调度组件,但不同的是允许子程序在特定的地方挂起和恢复。也就是调用A函数时可以执行到一半然后挂起去执行B函数,之后可以从A函数挂起的地方继续执行,例如下面的例子: 这个程序执行的结果是1 2 x 3 y z。从这个例子中我们可以对协程的定义有个很清晰的认识了。 了解了协程的定义,那么我们为什么需要协程呢,协程有什么的作用呢,接下来我们来看下协程的由来 起初人们喜欢同步编程,然后发现有一堆线程因为I/O卡在那里,并发上不去,资源严重浪费。 网络服务器模型一般为while(1){accept(); read(); do(); send()}。 然后出了异步(select,epoll,kqueue,etc),将I/O操作交给内核线程

unity协程

匿名 (未验证) 提交于 2019-12-03 00:22:01
开启协程 StartCoroutine (IEnumerator xxx);//里面传入协程方法 IEnumerator xxx(){}//协程方法定义 关于yied return 返回值 yield return null;//下一帧开始时继续调用 yiled return new WaitForFixedUpdate;//在FixedUpdate之后调用 yield return new WaitForSeconds (n);//N秒后继续运行 yield return WWW;//等待WWW构建完成后继续进行 协程进行逐步进行方法如下: yield return x1(调用协程); yield return x2(调用协程); 文章来源: unity协程

Lua coroutine协程

匿名 (未验证) 提交于 2019-12-03 00:18:01
coroutine : coroutine .create     --返回thread对象 coroutine .isyieldable coroutine .resume  coroutine .running coroutine .status coroutine .wrap    --返回function对象 coroutine .yield ( 1 ) coroutine .create (func)   传入一个函数参数,用来创建协程。返回一个“thread”对象。 ( 2 ) coroutine .isyieldable ()   如果正在运行的协程可以让出,则返回真。注意:只有主协程(线程)和C函数中是无法让出的。 ( 3 ) coroutine .resume (co [, val1, ・・・]) 用来启动或再次启动一个协程,使其由挂起状态变成运行状态。 coroutine .resume函数相当于执行协程中的方法。参数Val1...是执行协程co时传递给协程的方法。 首次执行协程co时,参数Val1...会传递给协程co的函数; 再次执行协程co时,参数Val1...会作为给协程co中上一次yeild的返回值。   resume函数返回什么呢?有 3 种情况:    1 )、如果协程co的函数执行完毕,协程正常终止,resume 返回 true 和函数的返回值。

协程基础及其创建和使用方法

匿名 (未验证) 提交于 2019-12-03 00:11:01
之前我们学习了线程、进程的概念,了解了在操作系统中进程是资源分配的最小单位,线程是CPU调度的最小单位。按道理来说我们已经算是把cpu的利用率提高很多了。但是我们知道无论是创建多进程还是创建多线程来解决问题,都要消耗一定的时间来创建进程、创建线程、以及管理他们之间的切换。 随着我们对于效率的追求不断提高,基于单线程来实现并发又成为一个新的课题,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发。这样就可以节省创建线进程所消耗的时间。 所以,产生协程的概念是为了实现: 单线程下实现并发 为此我们需要先回顾下并发的本质:切换+保存状态。 多线程实现并发:cpu正在运行一个任务(线程),会在两种情况下切走去执行其他的任务(切换由操作系统强制控制):,一种情况是该任务发生了阻塞,另外一种情况是该任务计算的时间过长。 如果是做纯计算任务的切换,这种切换反而会降低效率。 先在串行下执行计算任务: import time def eat (): print ( 'eat 1' ) # 疯狂计算的时候没有io(计算密集) time . sleep ( 2 ) for i in range ( 100000000 ): i += 1 def play (): print ( 'play 1' ) # 疯狂的计算的时候没有io(计算密集) time . sleep ( 3 ) for i