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
welkinzh
V2EX  ›  Python

关于 django 中使用 asyncio 的一个疑问

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

    在 django view 中使用 asyncio 去调用十次外部 api,经过测试确实比同步请求快,但是搜索 django asyncio 相关问题时,发现有人说:在 django view 中使用 asyncio,会阻塞整个 django worker,这一点有些不能理解,有人能解释一下吗,如果不使用异步请求,用 celery 的 group 去做,这两者有什么区别?

    问题来源: https://stackoverflow.com/questions/44667242/python-asyncio-in-django-view#comment88445130_44683173

    9 条回复    2019-04-01 11:58:23 +08:00
    so1n
        1
    so1n  
       2019-04-01 00:24:37 +08:00
    django 是同步的啊,自己本来的 request/response 周期也就是同步的(也就是一个 view )。如果你这个周期里面有十个外部 API 请求,那这个周期的时间能减少,但没有办法做到先返回响应,再去异步请求,可以使用 Django channel 来让 view 异步
    welkinzh
        2
    welkinzh  
    OP
       2019-04-01 00:33:04 +08:00 via iPhone
    @so1n 如果这个 view 的过程就是请求这些 api,然后处理返回的结果最后响应,那使用 asyncio 是不是就达到了减少响应时间这个目的呢,这样看的话,和使用 celery 的效果是一样的,我的理解对吗
    welkinzh
        3
    welkinzh  
    OP
       2019-04-01 00:44:33 +08:00 via iPhone
    我想我可能理解错那条评论的意思了,run_until_complete 会阻塞当前请求,而不会影响其他请求。贴上评论


    @Juanvulcano it works faster because you run async requests concurrently. However, loop.run_until_complete(main(language1, language2)) blocks further execution until async actions are complete. That means django worker won't be able to serve other requests till this one is complete.
    so1n
        4
    so1n  
       2019-04-01 00:57:12 +08:00
    @welkinzh run_until_complete 阻塞当前线程,一个请求开一个线程,应该不会阻塞到其他请求的。
    welkinzh
        5
    welkinzh  
    OP
       2019-04-01 00:59:12 +08:00 via iPhone
    @so1n 谢谢,理解了
    so1n
        6
    so1n  
       2019-04-01 01:02:33 +08:00
    @welkinzh 不过最好自己测试一下
    neoblackcap
        7
    neoblackcap  
       2019-04-01 07:22:03 +08:00   ❤️ 2
    @welkinzh 可以的,你的用法是正确的。你的使用相当于收集了好几个远程 API 的结果。不过嘛,一般我们不会这样使用 asyncio。如果你的处理牵涉到大量的网络请求,我建议你使用 Tornado 之类的框架进行网络 IO 重写,让 Tornado/asyncio 负责处理网络 IO,Django 这边就单纯地使用一个 requests 去请求 Tornado/asyncio 暴露出来的 API 就好了。
    Qzier
        8
    Qzier  
       2019-04-01 11:07:57 +08:00
    loop.run_until_complete() 是同步代码,当然会阻塞,再说了 Django 本来就是同步框架,如果你不想阻塞,要么用再开一个线程,要么把任务交给 Celery。
    welkinzh
        9
    welkinzh  
    OP
       2019-04-01 11:58:23 +08:00
    @Qzier 嗯嗯,只阻塞当前请求的线程就是我期望的结果了,因为我需要批量请求外部 api 然后处理 api 返回的结果。虽然会阻塞,但是比同步去请求快很多。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1740 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:31 · PVG 00:31 · LAX 08:31 · JFK 11:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.