相关疑难解决方法(0)

asyncio实际上如何工作?

这个问题是由我的另一个问题推动的:如何在cdef中等待?

网上有大量的文章和博客文章asyncio,但它们都非常肤浅.我找不到任何有关如何asyncio实际实现的信息,以及I/O异步的原因.我试图阅读源代码,但它是成千上万行不是最高级别的C代码,其中很多处理辅助对象,但最重要的是,很难在Python语法和它将翻译的C代码之间建立连接成.

Asycnio自己的文档甚至没那么有用.没有关于它是如何工作的信息,只有关于如何使用它的一些指导,这些指导有时也会误导/写得很差.

我熟悉Go的coroutines实现,并且希望Python做同样的事情.如果是这种情况,我在上面链接的帖子中出现的代码就可以了.既然没有,我现在正试图找出原因.到目前为止我最好的猜测如下,请纠正我错在哪里:

  1. 表单的过程定义async def foo(): ...实际上被解释为类继承的方法coroutine.
  2. 也许,async def实际上是通过await语句拆分成多个方法,其中调用这些方法的对象能够跟踪到目前为止通过执行所做的进度.
  3. 如果上述情况属实,那么,从本质上讲,协程的执行归结为一些全局管理器调用协程对象的方法(循环?).
  4. 全局管理器以某种方式(如何?)了解I/O操作何时由Python(仅?)代码执行,并且能够在当前执行方法放弃控制之后选择一个待执行的协程方法执行(命中await语句) ).

换句话说,这是我尝试将某些asyncio语法"贬低"为更容易理解的东西:

async def coro(name):
    print('before', name)
    await asyncio.sleep()
    print('after', name)

asyncio.gather(coro('first'), coro('second'))

# translated from async def coro(name)
class Coro(coroutine):
    def before(self, name):
        print('before', name)

    def after(self, name):
        print('after', name)

    def __init__(self, name):
        self.name = name
        self.parts = self.before, self.after
        self.pos = 0

    def __call__():
        self.parts[self.pos](self.name)
        self.pos += 1

    def …
Run Code Online (Sandbox Code Playgroud)

python python-3.x python-asyncio

64
推荐指数
5
解决办法
1万
查看次数

await 总是给其他任务一个执行的机会吗?

我想知道当事件循环切换任务时,python 提供了什么保证。

据我所知async/await从线程显著不同之处在于基于时间分片事件循环不切换任务,这意味着除非任务收益率(await),它会无限期地进行。这实际上很有用,因为在 asyncio 下管理临界区比使用线程更容易。

我不太清楚的是以下内容:

async def caller():
    while True:
        await callee()


async def callee():
    pass
Run Code Online (Sandbox Code Playgroud)

在这个例子中caller是重复的await。所以从技术上讲,它正在屈服。但是我不清楚这是否会允许事件循环上的其他任务执行,因为它只callee屈服于并且永远不会屈服。

也就是说,如果我callee在“关键部分”内等待,即使我知道它不会阻塞,我是否有发生其他意外事件的风险?

python async-await

8
推荐指数
1
解决办法
775
查看次数

wait协程和await任务之间的区别

get_1在 FastAPI 上,我有一个调用下面的协程函数的端点get_2

get_1用途await redis.get(key)

get_2用途await asyncio.ensure_future(redis.get(key))

这两个函数在功能和性能方面有什么区别吗?

#redis.py

import asyncio
import aioredis

async def get_1(key):
   redis = aioredis.from_url("redis://localhost")
   value = await redis.get(key)
   return value

async def get_2(key):
   redis = aioredis.from_url("redis://localhost")
   value = await asyncio.ensure_future(redis.get(key))
   return value
Run Code Online (Sandbox Code Playgroud)

python asynchronous python-asyncio fastapi aioredis

3
推荐指数
1
解决办法
3148
查看次数

python 协程超时

如何让协程因超时而停止?

我不明白为什么 asyncio.wait_for() 对我不起作用。我有这样一段代码(计划实现 telnet 客户端):

def expect(self, pattern, timeout=20): 
    if type(pattern) == str:
        pattern = pattern.encode('ascii', 'ignore')        
    return self.loop.run_until_complete(asyncio.wait_for(self.asyncxpect(pattern), timeout))

async def asyncxpect(self, pattern): #receives data in a cumulative way until match is found
    regexp = re.compile(b'(?P<payload>[\s\S]*)(?P<pattern>%s)' %pattern)
    self.buffer = b''
    while True:
        # add timeout
        # add exception handling for unexpectedly closed connections
        data = await self.loop.sock_recv(self.sock, 10000) 
        self.buffer += data
        m = re.match(regexp, self.buffer)
        if m:
            payload = m.group('payload')
            match = m.group('pattern')
            return payload, match 
Run Code Online (Sandbox Code Playgroud)

正如我所认为的,这段代码在某个时刻(在等待语句中)将控制权返回给事件循环。我认为当没有更多数据可以接收时应该发生这种情况。如果事件循环有控制权,它可以超时停止。

但是,如果服务器没有发送任何有用的(匹配的)我的代码就会在这个循环中绊倒,就在等待点。 …

python coroutine python-sockets python-asyncio

2
推荐指数
1
解决办法
2345
查看次数