生成器 g
生成器generator以及yield表达式详解
- ret = yield expression
- next(g)
- g.send(arg)
- g.throw(Exception)
- g.close()
- return msg
- StopIteration msg
点击查看代码
def my_generator(n):
for i in range(n):
temp = yield i
print(f'我是{temp}')
g = my_generator(5)
print(next(g)) # 输出0
print(next(g)) # 输出1
# g.send(100) # 本来输出2,但是传入新的值100,改为输出100
print(g.send(100))
print(next(g)) # 输出3
print(next(g)) # 输出4
'''
0#第一次迭代
---------------------
我是None
1#第二次迭代
---------------------
我是100#第三次迭代
---------------------
我是None#第四次迭代
3
---------------------
我是None#第五次迭代
4
'''
print('-------------------------')
def my_generator2():
try:
yield 'a'
yield 'b'
yield 'c'
yield 'd'
yield 'e'
except ValueError:
print('触发“ValueError"了')
except TypeError:
print('触发“TypeError"了')
g = my_generator2()
print(next(g))
print(next(g))
print('-------------------------')
print(g.throw(ValueError))
print('-------------------------')
print(next(g))
print(next(g))
print('-------------------------')
print(g.throw(TypeError))
print('-------------------------')
print(next(g))
print('-------------------------')
def my_generator3():
yield 1
return 'return返回了'
yield 2
g = my_generator3()
print(next(g))
print(next(g))
print(next(g))
生成器状态
使用yield关键字实现协程
Python协程详解(一)
- GEN_CREATED:等待执行
- GEN_RUNNING:解释器执行
- GEN_SUSPENDED:在yield表达式处暂停
- GEN_CLOSED:执行结束
点击查看代码
import datetime
from inspect import getgeneratorstate
from time import sleep
import threading
def get_state(coro):
while True:
print(datetime.datetime.now(), "其他线程生成器状态:%s", getgeneratorstate(coro))
sleep(1)
def simple_coroutine():
for i in range(3):
print(datetime.datetime.now(), 'simple_coroutine', i+1)
sleep(3)
x = yield i + 1
my_coro = simple_coroutine()
print(datetime.datetime.now(), "生成器初始状态:%s" % getgeneratorstate(my_coro))
t = threading.Thread(target=get_state, args=(my_coro,))
t.setDaemon(True)
t.start()
first = next(my_coro)
print(datetime.datetime.now(), 'simple_coroutine返回:', first)
print(datetime.datetime.now(), '开始循环')
for i in range(5):
try:
print(datetime.datetime.now(), 'simple_coroutine返回:', my_coro.send(i))
print(datetime.datetime.now(), "主线程生成器初始状态:%s" % getgeneratorstate(my_coro))
except StopIteration:
print(datetime.datetime.now(), "生成器的值拉取完毕")
print(datetime.datetime.now(), "生成器最后状态:%s" % getgeneratorstate(my_coro))
''' 输出结果:
2021-10-09 17:23:44.376290 生成器初始状态:GEN_CREATED
2021-10-09 17:23:44.378290 其他线程生成器状态:%s GEN_CREATED
2021-10-09 17:23:44.379277 simple_coroutine 1
2021-10-09 17:23:45.389752 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:46.396555 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:47.393188 simple_coroutine返回: 1
2021-10-09 17:23:47.393188 开始循环
2021-10-09 17:23:47.393188 simple_coroutine 2
2021-10-09 17:23:47.409192 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:48.419401 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:49.428855 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:47.393188 simple_coroutine返回: 2
2021-10-09 17:23:50.406583 主线程生成器初始状态:GEN_SUSPENDED
2021-10-09 17:23:50.406583 simple_coroutine 3
2021-10-09 17:23:50.437131 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:51.448273 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:52.459059 其他线程生成器状态:%s GEN_RUNNING
2021-10-09 17:23:50.406583 simple_coroutine返回: 3
2021-10-09 17:23:53.408010 主线程生成器初始状态:GEN_SUSPENDED
2021-10-09 17:23:53.408010 生成器的值拉取完毕
2021-10-09 17:23:53.408010 生成器的值拉取完毕
2021-10-09 17:23:53.408010 生成器的值拉取完毕
2021-10-09 17:23:53.408010 生成器最后状态:GEN_CLOSED
'''
生成器实现协程
使用yield关键字实现协程
点击查看代码
def consumer():
r = ''
while True:
n = yield r # 执行的中断点
if not n:
return
print('[消费者] 正在消费:{0}'.format(n))
r = f'{n * 100} 人民币' # 根据send进来的值返回不同的结果
def produce(c):
c.send(None) # 启动消费者(生成器)——实际上是函数调用,只不过生成器不是直接象函数那般调用的
n = 0
while n < 5:
n = n + 1
print('[生产者] 正在生产:{0}'.format(n))
r = c.send(n) # 给消费者传入值——实际上也是函数调用
print('[生产者] 消费者返回:{0}'.format(r))
print('-------------------------------------------------')
c.close()
c = consumer() # 构造一个生成器
produce(c)
'''运行结果为:
[生产者] 正在生产:1
[消费者] 正在消费:1
[生产者] 消费者返回:100 人民币
-------------------------------------------------
[生产者] 正在生产:2
[消费者] 正在消费:2
[生产者] 消费者返回:200 人民币
-------------------------------------------------
[生产者] 正在生产:3
[消费者] 正在消费:3
[生产者] 消费者返回:300 人民币
-------------------------------------------------
[生产者] 正在生产:4
[消费者] 正在消费:4
[生产者] 消费者返回:400 人民币
-------------------------------------------------
[生产者] 正在生产:5
[消费者] 正在消费:5
[生产者] 消费者返回:500 人民币
-------------------------------------------------
'''
yield from
yield from原理详解
点击查看代码
def my_generator():
for i in range(5):
if i == 3:
return '我被迫中断了'
else:
yield i
def wrap_my_generator(generator): # 定义一个包装“生成器”的生成器,它的本质还是生成器
result = yield from generator # 自动触发StopIteration异常,并且将return的返回值赋值给yield from表达式的结果,即result
print('wrap_my_generator', result)
def main(generator):
for j in generator:
print('main', j)
# def main(generator):
# print('main', next(generator))
# print('main', next(generator))
# # print('main', generator.throw(Exception('异常来了')))
# # print('main', generator.throw(StopIteration('异常来了')))
# print('main', next(generator))
# print('main', next(generator))
# print('main', next(generator))
g = my_generator()
wrap_g = wrap_my_generator(g)
main(wrap_g) # 调用
'''运行结果为:
main 0
main 1
main 2
wrap_my_generator 我被迫中断了
'''
Asyncio
asyncio的核心概念与基本架构
- coroutine(协程)
- yield/yield from (3.5之前)
- async/await (3.5及之后)
- event loop(事件循环)
- loop = asyncio.get_running_loop() (3.7版本加)
- loop = asyncio.get_event_loop()
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- 一个线程只能有一个event loop
- awaitable对象
- coroutine、Task、Future
- coroutine本质是一个函数,可自动封装成为Task,Task是Future的子类
- 创建任务
- loop.create_task(coro) 将协程转Task
- loop.create_future() 创建Future (这里是不是就把任务添加到事件循环里面了呢??)
- asyncio.create_task(coro) (3.7版本加)
- asyncio.ensure_future(coro_or_future) 当参数是coro时,函数里面调用的就是loop.create_task(coro) 3.5+版本参数coro_or_future可以是一个awaitable对象
- 多任务
- done,pending = await asyncio.wait([task1, task2,...])
- results = await asyncio.gather(*[task1, task2,...])
- 运行事件循环
- loop.run_until_complete(asyncio.wait([task1, task2,...]))
- loop.run_until_complete(asyncio.gather(*[task1, task2,...]))
- loop.run_until_complete(task)
- loop.run_forever()
- asyncio.run() (3.7版本加)
小例子
点击查看代码
import asyncio
import random
import sys
from datetime import datetime
# 3
async def consumer():
while True:
item = await queue.get()
print(datetime.now(), "I'm working hard", item)
await asyncio.sleep(random.random() * 3)
async def producer():
while True:
await queue.put(random.randint(0, sys.maxsize))
print(datetime.now(), 'count:', queue.qsize())
await asyncio.sleep(random.random() * 2)
# 2
# async def worker():
# print(datetime.now(), "I'm working hard")
#
#
# async def main():
# while True:
# asyncio.ensure_future(worker())
# await asyncio.sleep(random.random() * 2)
# 1
# def main():
# asyncio.ensure_future(consumer())
# asyncio.ensure_future(producer())
# 1 3
queue = asyncio.Queue()
# 1
# main()
loop = asyncio.get_event_loop()
# 1
# loop.run_forever()
# 2
# loop.run_until_complete(main())
# 3
loop.run_until_complete(asyncio.wait([consumer(), producer()]))