Всё равно ждёт. Асинхронный Python
Разбираюсь с аsync в Python.
Вроде понимаю особенность работы асинхронности,но в есть программа, где имеется долгое ожидание, и почему то диспетчер ожидает, вместо того, чтобы проверить другой объект.
Идея программы - доступность сетевых сервисов.
Используется библиотека pythonping для проверки доступности сервисов
import asyncio
from pythonping import ping
async def ping_host(host):
return ping(host).success() # True or False при проверке
async def check_host(host):
check = await ping_host(host)
if check:
print(host,'RUN')
else:
print(host, 'STOP')
tasks = [
asyncio.ensure_feature(check_host('srv-01')),
asyncio.ensure_feature(check_host('srv-02')),
asyncio.ensure_feature(check_host('srv-03'))]
event_manager = asyncio.get_event_loop()
event_manager.run_until_complete(asyncio.gather(*tasks))
event_manager.close()
Если указать просто check = await ping(host).success() то будет ошибка, поэтому async def ping_host.
Итак, что не так? В точке где check = await ping_host(host) если сервер недоступен, то ping очень долго ждёт(сек 4-5), поэтому здесь целесобразно переключиться к другой программе, пока ждём ответа, но почему то в моём коде это не работает.
В интеренете есть очень четкая блок-схема (https://yandex.ru/images/search?from=tabbar&text=асинхронный%20python%203&pos=7&img_url=https%3A%2F%2Fmedia.proglib.io%2Fwp-uploads%2F2018%2F07%2Fasync-programming-717x1024.jpg&rpt=simage) исходя из которого в моей программе в блоке (I/O, sleep), event_manager должен был загрузить task 2.
Ответы (1 шт):
async def ping_host(host):
return ping(host).success() # True or False при проверке
Модификатор async не превращает синхронную функцию автоматически в асинхронную. Да, вы теперь можете сделать такой функции await, но она не вернёт управление в момент ожидания, поскольку в самой этой функции нет ни одной конструкции await, при выполнении которой управление может возвращаться. Эта функция выполнится целиком и только тогда вернёт управление.
Правильнее всего в такой ситуации взять готовый асинхронный ping, например aioping. Пример использования из документации. Обратите внимание на await внутри функции do_ping:
import asyncio
import aioping
async def do_ping(host):
try:
delay = await aioping.ping(host) * 1000
print("Ping response in %s ms" % delay)
except TimeoutError:
print("Timed out")
loop = asyncio.get_event_loop()
loop.run_until_complete(do_ping("google.com"))
Можно при желании и самому превратить синхронную функцию в асинхронную, примеры можно найти здесь. Но обычно лучше всё-таки использовать библиотеку, которая "из коробки" поддерживает асинхронные вызовы.