这个问题是由我的另一个问题推动的:如何在cdef中等待?
网上有大量的文章和博客文章asyncio,但它们都非常肤浅.我找不到任何有关如何asyncio实际实现的信息,以及I/O异步的原因.我试图阅读源代码,但它是成千上万行不是最高级别的C代码,其中很多处理辅助对象,但最重要的是,很难在Python语法和它将翻译的C代码之间建立连接成.
Asycnio自己的文档甚至没那么有用.没有关于它是如何工作的信息,只有关于如何使用它的一些指导,这些指导有时也会误导/写得很差.
我熟悉Go的coroutines实现,并且希望Python做同样的事情.如果是这种情况,我在上面链接的帖子中出现的代码就可以了.既然没有,我现在正试图找出原因.到目前为止我最好的猜测如下,请纠正我错在哪里:
async def foo(): ...实际上被解释为类继承的方法coroutine.async def实际上是通过await语句拆分成多个方法,其中调用这些方法的对象能够跟踪到目前为止通过执行所做的进度.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 提供了什么保证。
据我所知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在“关键部分”内等待,即使我知道它不会阻塞,我是否有发生其他意外事件的风险?
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) 如何让协程因超时而停止?
我不明白为什么 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)
正如我所认为的,这段代码在某个时刻(在等待语句中)将控制权返回给事件循环。我认为当没有更多数据可以接收时应该发生这种情况。如果事件循环有控制权,它可以超时停止。
但是,如果服务器没有发送任何有用的(匹配的)我的代码就会在这个循环中绊倒,就在等待点。 …