代码之家  ›  专栏  ›  技术社区  ›  atline

为什么是蟒蛇。6是否可以从非协程生成器中的协程对象生成?

  •  0
  • atline  · 技术社区  · 6 年前

    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
      

    我知道我能做到 @asyncio.coroutine async/await

    但是,我的问题是:如果我仍然使用 generator ,python3的区别是什么。六,;蟒蛇3。7.我真的觉得这里很混乱。

    0 回复  |  直到 6 年前
        1
  •  0
  •   atline    6 年前

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

    • 在蟒蛇3。6,尽管 async/await 已经在那里了,, coroutine.sleep generator based 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()
      
    • 协同程序。睡觉 开始切换到 native coroutine

      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()
      

    所以,当蟒蛇3。6执行 yield from asyncio.sleep(1) 事实上,它并没有从本地协同程序中产生,当然也没有错误。