惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
Google DeepMind News
Google DeepMind News
U
Unit 42
博客园 - 叶小钗
博客园 - 聂微东
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
D
DataBreaches.Net
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Jina AI
Jina AI
美团技术团队
The Cloudflare Blog
M
MIT News - Artificial intelligence
Microsoft Azure Blog
Microsoft Azure Blog
I
InfoQ
S
Schneier on Security
C
Check Point Blog
Project Zero
Project Zero
The Hacker News
The Hacker News
Scott Helme
Scott Helme
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Cisco Talos Blog
Cisco Talos Blog
P
Privacy International News Feed
SecWiki News
SecWiki News
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
F
Fortinet All Blogs
博客园 - 三生石上(FineUI控件)
H
Help Net Security
TaoSecurity Blog
TaoSecurity Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Last Week in AI
Last Week in AI
P
Privacy & Cybersecurity Law Blog
Forbes - Security
Forbes - Security
G
GRAHAM CLULEY
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity
A
About on SuperTechFans
T
The Exploit Database - CXSecurity.com
C
Cisco Blogs
PCI Perspectives
PCI Perspectives
大猫的无限游戏
大猫的无限游戏
T
Troy Hunt's Blog
H
Hacker News: Front Page
Vercel News
Vercel News

Dvel's Blog

Rime 全拼双拼混输 CHD 油猴脚本:每日签到自动答题 Rime 配置:雾凇拼音 Hammerspoon 自动切换输入法 修复 Hugo 本地图片的累计布局偏移(CLS)问题 macOS 利用 Karabiner 修改 Emacs 键位为 Vim 键位 macOS 修改 Emacs 键位为 Vim 键位 Surge 配置 汉字的混乱 Netflix 中英双语字幕的好办法 优化 Rime 英文输入体验 判断字符是否为简体字或繁体字 Cloudflare 转入域名提示「出现了问题。请重试转移此域。尚未向您收费。」 图片压缩:Squoosh、TinyPNG、ImageOptim、WebP macOS grep + sed 批量替换多个文件的内容 在 macOS 根目录创建文件夹 博客图床小妙招 折腾 Hugo & PaperMod 主题 利用 Cloudflare Workers 进行批量 301 重定向 将博客部署在 Cloudflare Pages Alfred File Navigation(文件导航器)详解 在 Hugo Goldmark Markdown 中设置以新标签打开链接 日期与时间(UTC、GMT、时间戳、时区) 让 Alfred 以新标签的方式打开 Finder 用 git filter-branch 给 Git 仓库瘦身 qBittorrent 设置教程 联通光猫破解+桥接记录 配置 Mac 终端走代理 Steam for Mac 中文游戏推荐 我的 Mac 软件/工具列表 《Flask Web 开发》笔记 用 sleepwatcher 让 Mac 在睡眠及唤醒时自动执行一些脚本 解决 pyenv 导致的 brew warning 《SQL 必知必会》笔记 Git 自总结 再见,双点医院! 用 CloudXNS 解决 CNAME 与 MX 记录冲突 你好,Hugo! 为 Mac 打造 zsh command line 环境 新 Mac 新装修 秦皇岛暑期自驾的烦恼 苹果公司开发者账号申请流程 UIScrollView 中使用 Masonry 解决 CocoaPods 的类库 import 没有提示 iOS 使用 CocoaPods 的快速回顾 GitBook 简单生成本地静态 HTML 的方法 你好, Hexo! About
Python 异步 IO 笔记
Dvel · 2019-01-03 · via Dvel's Blog

协程初探

协程 - 廖雪峰 Python 教程

多进程与多线程均由操作系统调度,不过协程由程序员在协程的代码里显式调度。

协程没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

yield/send()

刚看廖老师协程一章的代码时是一脸懵逼,那么从 0 开始,了解 yield

10 年前的好文章: 深入理解 yield

看完再回顾廖老师的 [生产者-消费者] 模型:

def c():
	...
	n = yield r
	...

def p(c):
	...
	r = c.send(n)
	...

终于理解 yield 表达式与send() 函数两者皆可发送与反馈,协同工作,相辅相成。

send(n),p 发送了 n 给 c,c 怎么接收,yield 的返回值即是。

yield r,c 反馈了 r 给 p,p 怎么接收,send() 的返回值即是。

@asyncio.coroutine/yield from

yield from 语法由 Python 3.3 引进。

附:深入理解Python的yield from语法 ,摘抄部分代码:

# 子生成器
def average_gen():
    total = 0
    count = 0
    average = 0
    while True:
        new_num = yield average
        count += 1
        total += new_num
        average = total/count

# 委托生成器
def proxy_gen():
    while True:
        yield from average_gen()

# 调用方
def main():
    calc_average = proxy_gen()
    next(calc_average)            # 预激下生成器
    print(calc_average.send(10))  # 打印:10.0
    print(calc_average.send(20))  # 打印:15.0
    print(calc_average.send(30))  # 打印:20.0

if __name__ == '__main__':
    main()

asyncio 是 Python 3.4 版本引入的标准库,直接内置了对异步 IO 的支持。

asyncio 提供的 @asyncio.coroutine 可以把一个 generator 标记为 coroutine 类型,然后在 coroutine 内部用 yield from 调用另一个 coroutine 实现异步操作。

使用 yield from 关键字将一个 asyncio.Future 对象向下传递给事件循环,当这个 Future 对象还未就绪时,该协程就暂时挂起以处理其他任务。一旦 Future 对象完成,事件循环将会侦测到状态变化,会将 Future 对象的结果通过 send 方法方法返回给生成器协程,然后生成器恢复工作。

import asyncio

@asyncio.coroutine
def foo():
    print('foo start')
    yield from asyncio.sleep(5)
    print('foo end')

@asyncio.coroutine
def bar():
    print('bar start')
    yield from asyncio.sleep(10)
    print('bar end')

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([foo(), bar()]))
loop.close()

# 输出结果
# bar start
# foo start
# (等了5秒的IO操作)
# foo end
#(又等了5秒的IO操作)
# bar end

async/await

Python3.5 中引入的新语法 asyncawait 可以让协程代码更简洁易读,也让协程表面上与生成器区分开。

代码仅需进行简单的替换:

import asyncio

async def foo():
    print('foo start')
    await asyncio.sleep(5)
    print('foo end')

async def bar():
    print('bar start')
    await asyncio.sleep(10)
    print('bar end')

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait([foo(), bar()]))
loop.close()

另推荐一篇好文章:谈谈Python协程技术的演进