V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
aoscici2000
V2EX  ›  Python

Python 中关于 async/await 的疑问

  •  
  •   aoscici2000 · 2019-01-25 11:46:36 +08:00 · 2713 次点击
    这是一个创建于 2132 天前的主题,其中的信息可能已经有所发展或是发生改变。

    对于协程, 一些使用装饰器或者队列的实例基本都能理解, 但是这个 async/await 看了很多实例也不太懂该怎么理解. 网上 90%的教程的例子大概基本都是这样的:

    async def func():
        print("start...")
        r = await asyncio.sleep(5)
        print("end...")
    

    这个 asyncio.sleep()从一开始就定义是非阻塞的, 问题是它到底是通过什么方式实现非阻塞的呢? 换成我自己的处理函数, 这个函数应该用什么方式协程非阻塞的?

    10 条回复    2019-01-30 16:17:30 +08:00
    shylockhg
        1
    shylockhg  
       2019-01-25 11:49:55 +08:00
    asyncio.sleep 就是阻塞的,这里是模拟 IO 等阻塞过程
    shylockhg
        2
    shylockhg  
       2019-01-25 11:56:58 +08:00
    @shylockhg 说错应该叫非阻塞
    aoscici2000
        3
    aoscici2000  
    OP
       2019-01-25 12:01:27 +08:00
    @shylockhg 我疑问就是这里了, 这个非阻塞是通过什么方式实现的?
    so1n
        4
    so1n  
       2019-01-25 12:07:09 +08:00 via Android
    @aoscici2000 通过事件循环,3.4 时是 yield
    aoscici2000
        5
    aoscici2000  
    OP
       2019-01-25 12:10:53 +08:00
    @so1n 意思是该开线程还得开, 该 yield 还得 yield, 就是换了个词而已 ???
    silkriver
        6
    silkriver  
       2019-01-25 12:23:33 +08:00 via Android
    不开线程,异步 io 的意思就是 io 操作不会阻塞当前线程
    meik2333
        7
    meik2333  
       2019-01-25 12:31:41 +08:00 via Android
    https://github.com/python/cpython/blob/97cf0828727ac2a269c89c5aa09570a69a22c83c/Lib/asyncio/tasks.py#L593
    将事件添加到事件循环里,由事件循环调度。

    scrapy 也是用这种方法实现每分钟打印一次日志的。
    Trim21
        8
    Trim21  
       2019-01-25 12:34:12 +08:00
    你可以看看源码, asyncio.sleep 是通过在事件循环里 call_later 来实现的. 在这个 async 函数中阻塞, 但是不会阻塞事件循环.
    作用就是模拟异步 io 操作.
    所以换成你自己的处理函数的时候, 比如是链接数据库, http 请求这样的可以异步化的, 就用类似的异步化的库(比如 aiohttp, aioredis, motor 等等)来 await query()调用.
    如果不能异步化的就开线程用 ThreadPoolExecutor 转成异步调用.
    aijam
        9
    aijam  
       2019-01-25 12:39:05 +08:00
    解释线程 /异步 /非阻塞 /event loop 的文章网上一大堆,你看了也不会真的懂。
    先熟悉熟悉这个包:
    https://docs.python.org/3/library/selectors.html#module-selectors
    https://docs.python.org/3/library/select.html#module-select
    他们说的再多虚头巴脑都扯淡,核心内容就是 selector。
    xinXinDaWang
        10
    xinXinDaWang  
       2019-01-30 16:17:30 +08:00
    那你要看很多了,future, loop, epoll 都要看, 是他们相互协作形成的,await==yield from 只是一个方便的写法,也可以用回调来写,只是会麻烦一些
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3760 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 10:32 · PVG 18:32 · LAX 02:32 · JFK 05:32
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.