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 写一个协程函数

  •  
  •   aoscici2000 · 2019-04-09 10:44:41 +08:00 · 2577 次点击
    这是一个创建于 1815 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网上列举了不少例子, 基本都是使用 asyncio.sleep()来模拟, 但基本没说这个是如何实现非阻塞的, 也有说普通函数加个 async 就是协程函数了, 然后试了一下使用普通函数加个 async 关键字替代 asyncio.sleep, 行不通, 并不是同时执行的. 能简单给个例子不用官方的 sleep 是怎么实现这个协程的吗?

    
    from datetime import datetime
    import asyncio
    
    async def add(n):
        print(datetime.now().strftime('%H:%M:%S.%f'))
        count = 0
        for i in range(n):
            count += i
        print(datetime.now().strftime('%H:%M:%S.%f'))
        return count
    
    async def fun(n):
        res = await add(n)
        print(f'res = {res}')
    
    loop = asyncio.get_event_loop()
    tasks = [fun(20000000), fun(30000000)]
    loop.run_until_complete(asyncio.wait(tasks))
    loop.close()
    
    
    10 条回复    2019-04-10 09:41:42 +08:00
    silkriver
        1
    silkriver  
       2019-04-09 10:49:18 +08:00
    asyncio 是指异步 IO,对 IO 密集型操作有效,你这又不是 IO 操作能有什么用
    keepeye
        2
    keepeye  
       2019-04-09 11:13:45 +08:00
    asyncio.sleep() 可以用来模拟异步 io 但你的 add 方法里面没有异步操作啊。另外同时执行是伪命题,单线程,不可能同时执行的
    aoscici2000
        3
    aoscici2000  
    OP
       2019-04-09 11:47:45 +08:00 via iPhone
    @keepeye 最大疑问就是这个了,如果我需要 add 方法变成异步操作,那是不是也得单独开一个线程执行?如果是那感觉写起来也繁琐阿,为什么都说 async 这个关键字大大简化了异步操作了呢。
    Leigg
        4
    Leigg  
       2019-04-09 12:06:48 +08:00 via iPhone
    因为多数人自己都没明白,都是在模仿
    keepeye
        5
    keepeye  
       2019-04-09 12:11:27 +08:00
    @aoscici2000 如果你是为了防止耗时计算阻塞主线程,可以使用 loop.run_in_executor,通过别的线程处理完了再回调
    rexyan
        6
    rexyan  
       2019-04-09 12:14:46 +08:00
    可以看下 aiomysql 的 demo
    exiledkingcc
        7
    exiledkingcc  
       2019-04-09 16:40:03 +08:00   ❤️ 2
    你没搞清楚异步是什么。
    比如一个函数 f 需要执行 a,b,c 三个步骤操作,耗时比如是 1ms,100ms,1ms。其中 b 是 io 操作,比如网络请求,需要等待结果返回。而需要执行多个 f()。同步的情况就是:
    a();b();c();a();b();c();一共需要 204ms。
    异步的情况就是:
    a();b(),然后 b()中阻塞了,直接返回,开始执行第二个任务的 a(),b(),第二个 b()也阻塞了,然后就等待 io 完成,再然后执行后面的。一共需要 105ms。
    异步不是“同时执行”,而是原来同步需要等待 io,异步下可以去执行其它的 cpu 任务,这样就节约了原来浪费掉的 cpu 时间。看上去像是“同时执行”,实际上是“同时等待”,cpu 执行时间没法减少。
    asyncio.sleep 实际上就是让出 cpu 去执行别的任务,某个时间后再唤醒。
    Wicked
        8
    Wicked  
       2019-04-09 18:25:28 +08:00 via iPhone
    感觉楼主需要的是并行,python 没法多线程并行
    wwqgtxx
        9
    wwqgtxx  
       2019-04-09 18:57:05 +08:00
    asyncio 的主要用途在于等待 IO 操作,你这程序从头到尾都不涉及到 IO 操作( python 不目前支持异步 stdout ),当然没有任何作用,建议你对比一下 requests 和 aiohttp 并发请求网络资源的代码就知道区别了
    lucays
        10
    lucays  
       2019-04-10 09:41:42 +08:00
    简化异步操作仅仅是指 async/await 代替了 @asyncio.coroutine/yield from 而已吧
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3158 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 12:22 · PVG 20:22 · LAX 05:22 · JFK 08:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.