为什么python3.6可以从非协程生成器中的协程对象生成?

为什么python3.6可以从非协程生成器中的协程对象生成?,python,python-3.x,python-asyncio,Python,Python 3.x,Python Asyncio,zz.py import asyncio # @asyncio.coroutine def main(): yield from asyncio.sleep(1) next(main()) 在Python 3.6.7-->中执行,正常,无错误 在Python 3.7.3中执行-->不正常,报告如下: zz.py:5: RuntimeWarning: coroutine 'sleep' was never awaited yield from asyncio.slee

zz.py

import asyncio

# @asyncio.coroutine
def main():
    yield from asyncio.sleep(1)

next(main())
  • 在Python 3.6.7-->中执行,正常,无错误

  • 在Python 3.7.3中执行-->不正常,报告如下:

      zz.py:5: RuntimeWarning: coroutine 'sleep' was never awaited
        yield from asyncio.sleep(1)
      RuntimeWarning: Enable tracemalloc to get the object allocation traceback
      Traceback (most recent call last):
        File "zz.py", line 7, in <module>
          next(main())
        File "zz.py", line 5, in main
          yield from asyncio.sleep(1)
      TypeError: cannot 'yield from' a coroutine object in a non-coroutine generator
    
    zz.py:5:RuntimeWarning:coroutine'sleep'从未被等待过
    asyncio.sleep的产量(1)
    RuntimeWarning:启用tracemalloc以获取对象分配回溯
    回溯(最近一次呼叫最后一次):
    文件“zz.py”,第7行,在
    下一步(main())
    文件“zz.py”,第5行,主
    asyncio.sleep的产量(1)
    TypeError:无法从非协程生成器中的协程对象“屈服”
    
我知道我可以启用
@asyncio.coroutine
使两者都能工作,或者
async/await


但是,我的问题是:如果我仍然使用
generator
,那么python3.6和python3.7的区别是什么?我真的觉得这里很混乱。

在深入研究python源代码后,我找到了根本原因:

  • 在python3.6中,虽然已经有了
    async/await
    ,但
    coroutine.sleep
    仍然使用
    基于生成器的coroutine

    @coroutine
    def sleep(delay, result=None, *, loop=None):
        """Coroutine that completes after a given time (in seconds)."""
        if delay == 0:
            yield
            return result
    
        if loop is None:
            loop = events.get_event_loop()
        future = loop.create_future()
        h = future._loop.call_later(delay,
                                    futures._set_result_unless_cancelled,
                                    future, result)
        try:
            return (yield from future)
        finally:
            h.cancel()
    
    async def sleep(delay, result=None, *, loop=None):
        """Coroutine that completes after a given time (in seconds)."""
        if delay <= 0:
            await __sleep0()
            return result
    
        if loop is None:
            loop = events.get_event_loop()
        future = loop.create_future()
        h = loop.call_later(delay,
                            futures._set_result_unless_cancelled,
                            future, result)
        try:
            return await future
        finally:
            h.cancel()
    
  • 在python3.7中,
    coroutine.sleep
    开始切换到
    native coroutine

    @coroutine
    def sleep(delay, result=None, *, loop=None):
        """Coroutine that completes after a given time (in seconds)."""
        if delay == 0:
            yield
            return result
    
        if loop is None:
            loop = events.get_event_loop()
        future = loop.create_future()
        h = future._loop.call_later(delay,
                                    futures._set_result_unless_cancelled,
                                    future, result)
        try:
            return (yield from future)
        finally:
            h.cancel()
    
    async def sleep(delay, result=None, *, loop=None):
        """Coroutine that completes after a given time (in seconds)."""
        if delay <= 0:
            await __sleep0()
            return result
    
        if loop is None:
            loop = events.get_event_loop()
        future = loop.create_future()
        h = loop.call_later(delay,
                            futures._set_result_unless_cancelled,
                            future, result)
        try:
            return await future
        finally:
            h.cancel()
    
    async def sleep(延迟,结果=None,*,循环=None):
    “”“在给定时间(以秒为单位)后完成的协同路由。”
    如果延迟