Как отправить сообщение в Telegram, не блокируя основную ветку

from telegram import Bot
import asyncio

TOKEN = "blah"
CHAT_ID = 1

async def send_message_async():
    message = "This is a test update from the bot!"
    bot = Bot(token=TOKEN)
    await bot.send_message(chat_id=CHAT_ID, text=message)
    print("Message sent successfully!")


async def main():

    print("Before sending message...")

    await send_message_async()

    print("After sending message...") # I don't want this to be blocked until the message is sent


if __name__ == "__main__":
    asyncio.run(main())

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

Я надеюсь найти более простой API для решения вышеуказанной проблемы. Что-то вроде ниже

def send_message():
    # Sends message to user asynchonously without blocking the main thread
    pass

def main():
    # Main function
    send_message()

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

если вы не хотите его блокировать, запустите бота отдельно thread или process. OR don't use await`, потому что он ждет завершения функции, но используйте asyncio create_task().

furas 26.06.2024 05:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если не хочешь ждать, не ставь await, но create_task()

task = asyncio.create_task(send_message_async())

Вы можете использовать await task в конце программы, чтобы проверить, можете ли вы выйти из программы
или вам придется дождаться завершения этой задачи.

# wait for end of task
await task
# or 
result = await task

Вы также можете использовать if task.done():, чтобы проверить его, не блокируя код.

if task.done():
    result = await task
else:
    # ...

from telegram import Bot
import asyncio

TOKEN = "blah"
CHAT_ID = 1

async def send_message_async():
    print('starting send_message_async()')
    message = "This is a test update from the bot!"
    #bot = Bot(token=TOKEN)
    #await bot.send_message(chat_id=CHAT_ID, text=message)
    await asyncio.sleep(3)
    print("Message sent successfully!")

async def main():

    print("Before sending message...")

    task = asyncio.create_task(send_message_async())
    #await send_message_async()

    print("After sending message...")

    await asyncio.sleep(6)

    print("End...")

    # wait for end of task (to makes sure it finished)
    await task

if __name__ == "__main__":
    asyncio.run(main())

Пример с дополнительным print(), чтобы показать, что функции выполняются одновременно.

from telegram import Bot
import asyncio

TOKEN = "blah"
CHAT_ID = 1

async def send_message_async():
    print('starting send_message_async()')
    message = "This is a test update from the bot!"
    #bot = Bot(token=TOKEN)
    #await bot.send_message(chat_id=CHAT_ID, text=message)
    
    for i in range(10):
        print('sending', i)
        await asyncio.sleep(0.5)
        
    print("Message sent successfully!")

    return "It's done!"

async def main():

    print("main: Before sending message...")

    task = asyncio.create_task(send_message_async())
    #await send_message_async()
    await asyncio.sleep(0.01)
    #print(dir(task)) # 
    
    print("main: After sending message...")

    for i in range(3):
        print('main', i)
        await asyncio.sleep(0.5)

    print("main: End")

    while not task.done():
        print('main: waiting for end of task')
        await asyncio.sleep(1)

    # wait for end of task
    #await task 
    result = await task  # if function use `return` to send result
    print('main: result:', result)
        
if __name__ == "__main__":
    asyncio.run(main())

Результат:

main: Before sending message...
starting send_message_async()
sending 0
main: After sending message...
main 0
sending 1
main 1
sending 2
main 2
sending 3
main: End
main: waiting for end of task
sending 4
sending 5
main: waiting for end of task
sending 6
sending 7
main: waiting for end of task
sending 8
sending 9
main: waiting for end of task
Message sent successfully!
main: result: It's done!

Спасибо! Это работает так, как я задумал, и я буду использовать это. но есть ли способ избежать определения main как асинхронной функции? Например, .then в JavaScript вместо await.

Appaji Chintimi 26.06.2024 18:23

в JavaScript все асинхронно, и .then запускает его также как асинхронный код, поэтому может потребоваться еще один .then для работы с результатами предыдущих .then - fetch().then().then(). И у него есть встроенный асинхронный цикл, поэтому ему не нужна asyncio.run(), но в Python нет встроенного асинхронного цикла, поэтому ему нужна asyncio.run() и run() нужна асинхронная функция main(). Но в JavaScript вы также можете использовать await для запуска кода как обычной функции.

furas 26.06.2024 19:00

в Python create_task() работает как обычная функция в JavaScript. Насколько я помню, у него есть функция .add_done_callback(), которую можно выполнить в конце функции, но я ее не проверял.

furas 26.06.2024 19:12

Разница между асинхронным ожиданием в Python и JavaScript – 1 Ответ

furas 26.06.2024 19:13

Я нашел модуль promisio, который работает как JavaScript - он есть then()

furas 26.06.2024 19:23

Понятно, я все еще пытаюсь надеть это на голову. но сейчас я просто признаю, что мне нужно определить, что моя родительская функция (main) должна быть асинхронной. хаха

Appaji Chintimi 26.06.2024 20:22

Другие вопросы по теме