Допустим, мне поручено перенести проект Flask на asyn c Python веб-сервер. Я ищу шаблоны, чтобы минимизировать объем работы здесь. Мне кажется, более или менее, невозможно постепенно портировать syn c веб-серверы в asyn c веб-серверы. Это заставляет меня думать, что я неправильно понял asyn c.
Предположим, я хочу использовать библиотеку asyncio sql и использовать ее на веб-сервере asyncio, возможно, нам придется изменить следующий стек методы asyn c:
if __name__=='__main__':
asyncio.get_event_loop().run_until_complete(main)
> async def main()
> async def subfunc()
> async def subsubfunc()
> async def decorator1()
> async def decorator2()
> async def webapi()
> async def decorator3()
> async def decorator4()
> async def servicemethod()
> async def servicemethod_impl()
....
> async def decorator5()
> async def decorator6()
> async def repositorylayer()
> async def sqllibrary()
> async def sqllibrary2()
> async def asyncio_socket.read()
^^, потому что мы хотим ждать asyncio_socket.read (), тогда каждая функция в стеке должна быть изменена, имеет объявление функции async def
, а также await
на его зависимость. Это имеет некоторые серьезные последствия для рефакторинга:
- нам нужно изменить функцию до n, чтобы получить преимущество одного asyncio_socket.read (), большинство из которых мало заботятся о том, является ли чтение сокета syn c или asyn c. То есть мы ДОЛЖНЫ объявить каждую зависимую функцию асинхронной c и ожидать результата зависимости (!)
- . Любая функция, которая раньше зависела от какой-либо функции в этом стеке (но не в этом стеке), также должна измениться на быть асин c. (!) Тесты модулей событий, которые могут быть нам не интересны при переходе на asyn c сегодня, должны быть изменены:
result = oldtest()
assert result==expected
result = asyncio.get_event_loop().run_until_complete(oldtest())
assert result==expected
Как правило, любая функция syn c, которая вызывает Функция asyn c нуждается в рефакторинге asyn c -await - то есть asyn c - это сложная функция. Любой код, который вызывает asyn c, должен быть заражен asyn c, независимо от того, заботится ли он об asyn c или нет.
Поскольку это означает глобальный рефакторинг, постепенный прирост не представляется возможным перенесите веб-сервис с syn c -land на asyn c -land в любом проекте, кроме самых маленьких. Я видел решения, которые перемещают выполнение в потоки на барьере sync / asyn c. Тем не менее, кажется, что это: - создает проблемы безопасности потоков - устраняет преимущества asyn c должны быть коммуникация и переключение контекста - уменьшает пропускную способность выполнения из-за GIL.
Однако, в принципе, это должно быть возможным для вызова асинхронных c функций из syn c function:
def syncfunc2():
result = asyncio.get_event_loop().run_until_complete(asyncfunc1())
return result
async def asyncfunc3():
result = await asyncfunc2()
return result
def syncfunc4():
result = asyncio.get_event_loop().run_until_complete(asyncfunc3())
return result
Однако по непонятной причине Python не позволяет этого и завершается с:
RuntimeError: This event loop is already running
Я думаю, что - это , позволяющее безопасно реализовать повторяющиеся циклы событий. Мы используем это для потоковых исполнителей, когда у нас закончились потоки - вызывающая функция run_until_complete может управлять выполнением события l oop до тех пор, пока оно не вернется, после чего выполнение возвращается исходному исполнителю (что предотвращает тупики исполнителей, но ожидающих исполнения). Это особенно просто в Python, потому что GIL позволяет нам тривиально гарантировать, что event_l oop либо:
- не управляется другой функцией,
- ожидает текущая функция для вызова await
и поэтому безопасно извлечь задачу из очереди и выполнить ее. Поскольку Python жалуется, если вы повторно вводите run_until_complete, это запрещает это, а также запрещает добавочное введение asyn c.
Итак:
- почему не запускается run_until_complete?
- возможно ли постепенно вводить асин c в большом кодовые базы без обращения к дополнительным потокам (и соответствующая потеря выгоды asyn c).
- - это тот случай, когда asyn c эффективно раздвоил кодовую базу python в тех библиотеках, которые используют asyn c, а те что нет?
Похожие: