Как на самом деле работает asyncio?Python

Программы на Python
Ответить
Anonymous
 Как на самом деле работает asyncio?

Сообщение Anonymous »

Этот вопрос мотивирован другим моим вопросом: Как ждать в cdef?

В Интернете есть множество статей и сообщений в блогах об asyncio, но все они очень поверхностны. Мне не удалось найти никакой информации о том, как на самом деле реализован asyncio и что делает ввод-вывод асинхронным. Я пытался прочитать исходный код, но это тысячи строк кода C не самого высокого качества, многие из которых связаны со вспомогательными объектами, но, что наиболее важно, трудно связать синтаксис Python с тем, в какой код C он будет транслироваться.

Собственная документация Asycnio еще менее полезна. Там нет информации о том, как это работает, только некоторые рекомендации по его использованию, которые также иногда вводят в заблуждение или очень плохо написаны.

Я знаком с реализацией сопрограмм в Go и надеялся, что Python делает то же самое. Если бы это было так, код, который я привел в сообщении, указанном выше, работал бы. Поскольку этого не произошло, я сейчас пытаюсь выяснить, почему. На данный момент мое лучшее предположение таково, пожалуйста, поправьте меня, где я ошибаюсь:
  • Определения процедур в форме async def foo(): ... на самом деле интерпретируются как методы класса, наследующего сопрограмму.
  • Возможно, async def фактически разделяется на несколько методов с помощью операторов await, где объект, для которого вызываются эти методы способен отслеживать ход выполнения на данный момент.
  • Если вышеизложенное верно, то, по сути, выполнение сопрограммы сводится к вызову методов объекта сопрограммы неким глобальным менеджером (цикл?).
  • Глобальный менеджер каким-то образом (как?) знает, когда операции ввода-вывода выполняются кодом 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 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()
Если моя догадка окажется верной: тогда у меня проблема. Как на самом деле происходит ввод-вывод в этом сценарии? В отдельной теме? Весь интерпретатор приостановлен и ввод-вывод происходит вне интерпретатора? Что именно подразумевается под вводом-выводом? Если моя процедура Python вызвала процедуру C open() и она, в свою очередь, отправила прерывание ядру, передав ему управление, как интерпретатор Python узнает об этом и сможет продолжить выполнение некоторого другого кода, в то время как код ядра выполняет фактический ввод-вывод и пока он не разбудит процедуру Python, которая изначально отправила прерывание? Как интерпретатор Python в принципе может знать об этом?

Подробнее здесь: https://stackoverflow.com/questions/490 ... ually-work
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»