初学 python,大家帮忙看看这段协程代码,运行结果想了半天还没想通 - V2EX
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
nicegoing
V2EX    Python

初学 python,大家帮忙看看这段协程代码,运行结果想了半天还没想通

  •  
  •   nicegoing 2016 年 11 月 3 日 5248 次点击
    这是一个创建于 3359 天前的主题,其中的信息可能已经有所发展或是发生改变。
    import logging; logging.basicConfig(level=logging.INFO) import asyncio, os, json, time from datetime import datetime from aiohttp import web def index(request): logging.info('server response...') return web.Response(body=b'<h1>Awesome</h1>') async def init(loop): app = web.Application(loop=loop) app.router.add_route('GET', '/', index) logging.info('server before...') srv = await loop.create_server(app.make_handler(), '127.0.0.1', 9000) logging.info('server started at http://127.0.0.1:9000...') return srv loop = asyncio.get_event_loop() loop.run_until_complete(init(loop)) loop.run_forever() 

    我觉得运行的日志:

    INFO:root:server before... INFO:root:server response... INFO:root:server started at http://127.0.0.1:9000... 

    结果正确的日志是:

    INFO:root:server before... INFO:root:server started at http://127.0.0.1:9000... INFO:root:server response... 

    在我的理解里, python 执行到 await 应该暂停执行函数, TCP 协程结束后,才执行 server started at...这条日志。怎么函数一下子全部执行完了。

    14 条回复    2016-11-03 11:03:45 +08:00
    cloverstd
        1
    cloverstd  
       2016 年 11 月 3 日 via iPhone
    因为你的 init 函数没有用 await init 调用
    ifaii
        2
    ifaii  
       2016 年 11 月 3 日
    async def init(loop):

    学艺不精 看不懂-_-||
    nicegoing
        3
    nicegoing  
    OP
       2016 年 11 月 3 日
    @cloverstd https://docs.python.org/3/library/asyncio-task.html#example-chain-coroutines
    这是 python 的官方示例。这个例子调用的时候也没有 await 调用呀
    ```
    import asyncio

    async def compute(x, y):
    print("Compute %s + %s ..." % (x, y))
    await asyncio.sleep(1.0)
    return x + y

    async def print_sum(x, y):
    result = await compute(x, y)
    print("%s + %s = %s" % (x, y, result))

    loop = asyncio.get_event_loop()
    loop.run_until_complete(print_sum(1, 2))
    loop.close()
    ```
    sujin190
        4
    sujin190  
       2016 年 11 月 3 日
    没错啊, create_server 只是 bing 了没有 listen 啊,所以立刻返回了, run_forever 才进行 listen 的行为
    nicegoing
        5
    nicegoing  
    OP
       2016 年 11 月 3 日
    @ifaii 我也不懂,纠结中
    sujin190
        6
    sujin190  
       2016 年 11 月 3 日
    没错啊, create_server 只是 bind 了没有 listen 啊,所以立刻返回了, run_forever 才进行 listen 的行为
    cloverstd
        7
    cloverstd  
       2016 年 11 月 3 日
    @nicegoing 你的 init 返回的是一个 future ,直接 init() 会当做普通函数来执行
    ruoyu0088
        8
    ruoyu0088  
       2016 年 11 月 3 日
    loop.create_server 是创建一个服务器对象, await loop.create_server(...)是等待创建这个服务器对象,并不是等待这个服务器响应请求。
    yufpga
        9
    yufpga  
       2016 年 11 月 3 日
    await 的语义相当于 yield from(首先你得先搞清楚这个东西), 不要和 yield 这个鬼搞混淆了, 出现 async 和 await 支持的原因本就是为了使用写同步代码的方式写出异步的效果.在你这里, 正常逻辑考虑, 你的 server 都还没有创建, 怎么可能请求成功, 从而执行 index 函数.建议 debug 追踪下代码内部的执行逻辑,要熟悉其内部原理, 最好看一下 asyncio 的源码, 自己实现一下
    nicegoing
        10
    nicegoing  
    OP
       2016 年 11 月 3 日
    @cloverstd
    @sujin190
    @ruoyu0088
    谢谢大家,有点儿明白了。
    nicegoing
        11
    nicegoing  
    OP
       2016 年 11 月 3 日
    @yufpga 感觉 yield from 和 yield 没什么大区别。谢谢,我去读读源码
    yufpga
        12
    yufpga  
       2016 年 11 月 3 日
    @sujin190 你的说法是有问题的, run_forever 并不是进行 server 的 listen 的行为,而是执行了一段类似与下面的代码
    while not self.stopped:
    events = selector.select(self.select_timeout)
    if not events:
    raise Exception('轮询超时')
    for event_key, event_mask in events:
    callback = event_key.data
    callback(event_key, event_mask)
    用来取出可读可写等事件, 其实就是通过事件循环驱动(通知)阻塞程序恢复执行
    sujin190
        13
    sujin190  
       2016 年 11 月 3 日
    @yufpga listen 做的事情也是这样的啊,有什么区别么
    lytofb
        14
    lytofb  
       2016 年 11 月 3 日
    没什么问题啊, win7 64 位 python 3.5.2
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3730 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 00:49 PVG 08:49 LAX 16:49 JFK 19:49
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86