推荐学习书目
› 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 · Nov 3, 2016 · 5945 views
    This topic created in 3656 days ago, the information mentioned may be changed or developed.
    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 replies  •  2016-11-03 11:03:45 +08:00
    cloverstd
    cloverstd
    Nov 3, 2016 via iPhone
    1
    因为你的 init 函数没有用 await init 调用
    ifaii
    ifaii
    Nov 3, 2016
    2
    async def init(loop):

    学艺不精 看不懂-_-||
    nicegoing
    nicegoing
    OP
    Nov 3, 2016
    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
    sujin190
    Nov 3, 2016
    4
    没错啊, create_server 只是 bing 了没有 listen 啊,所以立刻返回了, run_forever 才进行 listen 的行为
    nicegoing
    nicegoing
    OP
    Nov 3, 2016
    5
    @ifaii 我也不懂,纠结中
    sujin190
    sujin190
    Nov 3, 2016
    6
    没错啊, create_server 只是 bind 了没有 listen 啊,所以立刻返回了, run_forever 才进行 listen 的行为
    cloverstd
    cloverstd
    Nov 3, 2016
    7
    @nicegoing 你的 init 返回的是一个 future ,直接 init() 会当做普通函数来执行
    ruoyu0088
    ruoyu0088
    Nov 3, 2016
    8
    loop.create_server 是创建一个服务器对象, await loop.create_server(...)是等待创建这个服务器对象,并不是等待这个服务器响应请求。
    yufpga
    yufpga
    Nov 3, 2016
    9
    await 的语义相当于 yield from(首先你得先搞清楚这个东西), 不要和 yield 这个鬼搞混淆了, 出现 async 和 await 支持的原因本就是为了使用写同步代码的方式写出异步的效果.在你这里, 正常逻辑考虑, 你的 server 都还没有创建, 怎么可能请求成功, 从而执行 index 函数.建议 debug 追踪下代码内部的执行逻辑,要熟悉其内部原理, 最好看一下 asyncio 的源码, 自己实现一下
    nicegoing
    nicegoing
    OP
    Nov 3, 2016
    10
    @cloverstd
    @sujin190
    @ruoyu0088
    谢谢大家,有点儿明白了。
    nicegoing
    nicegoing
    OP
    Nov 3, 2016
    11
    @yufpga 感觉 yield from 和 yield 没什么大区别。谢谢,我去读读源码
    yufpga
    yufpga
    Nov 3, 2016
    12
    @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
    sujin190
    Nov 3, 2016
    13
    @yufpga listen 做的事情也是这样的啊,有什么区别么
    lytofb
    lytofb
    Nov 3, 2016
    14
    没什么问题啊, win7 64 位 python 3.5.2
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2106 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 132ms · UTC 02:44 · PVG 10:44 · LAX 18:44 · JFK 21:44
    ♥ Do have faith in what you're doing.