В Интернете есть множество статей и сообщений в блогах об asyncio, но все они очень поверхностны. Мне не удалось найти никакой информации о том, как на самом деле реализован asyncio и что делает ввод-вывод асинхронным. Я пытался прочитать исходный код, но это тысячи строк кода C не самого высокого качества, многие из которых связаны со вспомогательными объектами, но, что наиболее важно, трудно связать синтаксис Python с тем, в какой код C он будет транслироваться.
Собственная документация Asycnio еще менее полезна. Там нет информации о том, как это работает, только некоторые рекомендации по его использованию, которые также иногда вводят в заблуждение или очень плохо написаны.
Я знаком с реализацией сопрограмм в Go и надеялся, что Python делает то же самое. Если бы это было так, код, который я привел в сообщении, указанном выше, работал бы. Поскольку этого не произошло, я сейчас пытаюсь выяснить, почему. На данный момент мое лучшее предположение таково, пожалуйста, поправьте меня, где я ошибаюсь:
- Определения процедур в форме async def foo(): ... на самом деле интерпретируются как методы класса, наследующего сопрограмму.
- Возможно, async def фактически разделяется на несколько методов с помощью операторов await, где объект, для которого вызываются эти методы способен отслеживать ход выполнения на данный момент.
- Если вышеизложенное верно, то, по сути, выполнение сопрограммы сводится к вызову методов объекта сопрограммы неким глобальным менеджером (цикл?).
- Глобальный менеджер каким-то образом (как?) знает, когда операции ввода-вывода выполняются кодом Python (только?) и может выбрать один из ожидающих методов сопрограммы для выполнения после текущего исполняемого метода отказался от контроля (нажатие на оператор await).
Код: Выделить всё
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 done(self):
return self.pos == len(self.parts)
# translated from asyncio.gather()
class AsyncIOManager:
def gather(*coros):
while not every(c.done() for c in coros):
coro = random.choice(coros)
coro()
Подробнее здесь: https://stackoverflow.com/questions/490 ... ually-work
Мобильная версия