Всё равно ждёт. Асинхронный 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 шт):

Автор решения: CrazyElf
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"))

Можно при желании и самому превратить синхронную функцию в асинхронную, примеры можно найти здесь. Но обычно лучше всё-таки использовать библиотеку, которая "из коробки" поддерживает асинхронные вызовы.

→ Ссылка