104.协程

协程

  • 定义:为非抢占式多任务产生子程序的计算机程序组件
  • 协程允许不同入口点在不同位置暂停或开始执行程序
  • 从技术角度讲,协程是可以暂停的函数,或直接理解为生成器
  • 本质是单线程,相比多线程,可以及其节省系统资源
  • 协程函数运行结束后,如果还执行.send()就会报错StopIteration
  • yield即使返回值,也是可以是下一步的参数输入值
def xc():
    print("协程开始")
    #yield既是出口,也是入口
    a = yield
    print("协程从新开始:", a)

#实例一个协程
x = xc()

print("11111")
#此步骤可以使用next(x)
#开始执行,也叫预激
x.send(None)
print("22222")
x.send("haha")

inspect.getgeneratorstate(x) 查询协程的状态(inspect模块)

  • ‘GEN_CREATED‘ 等待开始执行。
  • ‘GEN_RUNNING‘ 解释器正在执行。
  • ‘GEN_SUSPENDED‘ 在 yield 表达式处暂停。
  • ‘GEN_CLOSED‘ 执行结束。

协程终止

  • 协程中文处理的异常,会向上传递给next或.seed方法的调用方
  • 止协程的另一种方法:发送哨符值,让协程推出,一内置的None或Ellipsis

yield from

  • 委派生成器

    • 包含yield from的生成器函数
def A():
    for i in [1, 2]:
        yield i

print(list(A()))

def B():
    #相当于在list和[1, 2]间的中间地带
    yield from [1, 2]

print(list(B()))

asyncio包

  • python3.4开始引入便准库,内置对异步IO的支持
  • asyncio本身是一个消息循环
  • 创建过程:
    1. 创建消息循环
    2. 把协程引入
    3. 关闭消息循环
import threading
import asyncio

@asyncio.coroutine
def hello():
    print('Hello world! (%s)' % threading.currentThread())
    #跳出协程,睡5秒
    yield from asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())

#启动消息循环
loop = asyncio.get_event_loop()
#定义要执行的任务
tasks = [hello(), hello()]
#asyncio使用wati等待task执行完毕
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
#执行结果
Hello world! (<_MainThread(MainThread, started 2400)>)
Hello world! (<_MainThread(MainThread, started 2400)>)
Hello again! (<_MainThread(MainThread, started 2400)>)
Hello again! (<_MainThread(MainThread, started 2400)>)

async 和 await

  • python3.5引入
  • 更好的表示异步io
  • 让协程代码更简洁
  • 在语法上可以简单的替换
    • async 替换 @asyncio.coroutine
    • await 替换 yield from

aidhttp

  • asyncio可以实现单线程并发IO操作
  • 客户端用处不大
  • 在服务器端,可以处理多用户的高并发用coroutine+单线程
  • asyncio实现了TCP.UDP.SSL等协议
  • aiohttp是给予asyncio的http框架
  • 不是标准模块,需安装

concurrent.futures

  • python3库
  • 线程池
    -利用multiprocessiong实现真正的并行计算,前提是cup得是多核
  • 原理已子进程的形式,并行运行多个python解释器,子进程和主进程是相互独立的,所以他们的全局解释器锁是相互独立的,每个子进程都能完整的使用一个cup内核
  • from concurrent.futures import ThreadPoolExecutor
    • ThreadPoolExecutor(max_workers=数量) 创建线程池,并指定线程数量,根据需要选择
    • ProcesspoolExecutor(max_workers=数量) 创建进程池,并指定进程数量,根据需要选择
    • .submit(fn, args, kwargs) 创建线程或进程 fn线程或进程函数的函数名
    • .done 线程执行的状态 Ture执行完毕, False未执行完毕
    • .result 线程或进程函数执行的结果
import time
from concurrent import futures

def return_futures(a):
    time.sleep(2)
    return a

#创建一个线程池,max_workers工作线程数量
s = futures.ThreadPoolExecutor(max_workers=2)
#向线程池中加入两个任务
r1 = s.submit(return_futures, "hi")
r2 = s.submit(return_futures, "hello")

#判断两个线程执行状态
print(r1.done())
print(r2.done())
time.sleep(3)
print(r1.done())
print(r2.done())

#输出两个线程的结果
print(r1.result())
print(r2.result())
  • .map()

    • 和map函数类似,映射
    • 异步执行
import time
from concurrent import futures

def wait_on(a):
    print(a)
    time.sleep(2)
    return "ok"

l = [1, 2]

t = futures.ThreadPoolExecutor(max_workers=2)
for i in t.map(wait_on, l):
    print(i)

原文地址:https://www.cnblogs.com/TK-tank/p/12316220.html

时间: 2024-10-11 10:28:39

104.协程的相关文章

Python基础—线程、进程和协程

今天已是学习Python的第十一天,来干一碗鸡汤继续今天的内容,今天的鸡汤是:超越别人对你的期望.本篇博客主要介绍以下几点内容: 线程的基本使用: 线程的锁机制: 生产者消费之模型(队列): 如何自定义线程池: 进程的基本使用: 进程的锁机制: 进程之间如何实现数据共享: 进程池: 协程的基本使用. 一.线程 1.创建线程 上篇博客已经介绍过如何创建多线程的程序,在这里在复习一下如何创建线程过程以及线程的一些方法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1

python协程函数、递归、匿名函数与内置函数使用、模块与包

目录: 协程函数(yield生成器用法二) 面向过程编程 递归 匿名函数与内置函数的使用 模块 包 常用标准模块之re(正则表达式) 一.协程函数(yield生成器用法二) 1.生成器的语句形式 a.生成器相关python函数.装饰器.迭代器.生成器,我们是如何使用生成器的.一个生成器能暂停执行并返回一个中间的结果这就是 yield 语句的功能 : 返回一个中间值给调用者并暂停执行. 我们的调用方式为yeild 1的方式,此方式又称为生成器的语句形式. 而使用生成器的场景:使用生成器最好的场景就

python线程、进程和协程

链接:http://www.jb51.net/article/88825.htm 引言 解释器环境:python3.5.1 我们都知道python网络编程的两大必学模块socket和socketserver,其中的socketserver是一个支持IO多路复用和多线程.多进程的模块.一般我们在socketserver服务端代码中都会写这么一句: server = socketserver.ThreadingTCPServer(settings.IP_PORT, MyServer) Threadi

Java协程框架-Kilim字节码剖析

前面几篇文章从代码层面介绍了Kilim的基本原理,但是对于其中的一些细节,比如Task的执行状态如何管理等问题从代码上依然得不到答案,本文即再深入到字节码层面来解答. 1.  Kilim字节码改写前后的代码有什么区别? 这里还是先上Kilim官方文档中的一张图,这张图清晰的展现出原始的代码与经Kilim改写后的协程代码. 可以看出左边的原始代码,与我们常见的函数相比有所不同,这里显示声明抛出Pausable异常.实际上这个异常在运行期间不会抛出,它的实际作用类似于注解,使得Kilim能够识别哪些

单线程、多线程、多进程、协程比较,以爬取新浪军事历史为例

演示python单线程.多线程.多进程.协程 1 import requests,json,random 2 import re,threading,time 3 from lxml import etree 4 5 lock=threading.Lock() 6 semaphore=threading.Semaphore(100) ###每次限制只能100线程 7 8 user_agent_list = [ 9 "Mozilla/5.0 (Windows NT 6.1; WOW64) Appl

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

多进程、协程、事件驱动及select poll epoll

目录 -多线程使用场景 -多进程 --简单的一个多进程例子 --进程间数据的交互实现方法 ---通过Queues和Pipe可以实现进程间数据的传递,但是不能实现数据的共享 ---Queues ---Pipe ---通过Manager可以不同进程间实现数据的共享 --进程同步,即进程锁 --进程池 -协程 --先用yield实现简单的协程 --Greenlet --Gevent --用协程gevent写一个简单并发爬网页 -事件驱动 --IO多路复用 ---用户空间和内核空间 ---文件描述符fd

Python线程和协程-day10

写在前面 上课第10天,打卡: 感谢Egon老师细致入微的讲解,的确有学到东西! 一.线程 1.关于线程的补充 线程:就是一条流水线的执行过程,一条流水线必须属于一个车间: 那这个车间的运行过程就是一个进程: 即一个进程内,至少有一个线程: 进程是一个资源单位,真正干活的是进程里面的线程: 线程是一个执行单位: 多线程:一个车间内有多条流水线,多个流水线共享该车间的资源: 一个进程内有多个线程,多线程共享一个进程的资源: 线程创建的开销要远远小于创建进程的开销: 进程之间更多的是一种竞争关系:

线程、进程、协程和队列

一.线程.进程 1.简述 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,通俗讲就是自定义一段程序的执行过程,即一个正在运行的程序.线程是进程的基本单位,又称为轻量级进程. * 不同的进程在内存中会开辟独立的地址空间,默认进程之间的数据是不共享,线程是由进程创建,所以处在同一个进程中的所有线程都可以访问该进程所包含的地址空间,当然也包含存储在该空间中的所有资源. 应用场景: IO密集型操作由于不占用CPU资源,所以一般使用线程来完成 计算密集型操作