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()
Но похоже, что для вызова одной асинхронной функции все остальные функции должны быть преобразованы в асинхронную функцию.
Если не хочешь ждать, не ставь 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
.
в JavaScript все асинхронно, и .then
запускает его также как асинхронный код, поэтому может потребоваться еще один .then
для работы с результатами предыдущих .then
- fetch().then().then()
. И у него есть встроенный асинхронный цикл, поэтому ему не нужна asyncio.run()
, но в Python нет встроенного асинхронного цикла, поэтому ему нужна asyncio.run()
и run()
нужна асинхронная функция main()
. Но в JavaScript вы также можете использовать await
для запуска кода как обычной функции.
в Python create_task()
работает как обычная функция в JavaScript. Насколько я помню, у него есть функция .add_done_callback()
, которую можно выполнить в конце функции, но я ее не проверял.
Разница между асинхронным ожиданием в Python и JavaScript – 1 Ответ
Я нашел модуль promisio, который работает как JavaScript - он есть then()
Понятно, я все еще пытаюсь надеть это на голову. но сейчас я просто признаю, что мне нужно определить, что моя родительская функция (main
) должна быть асинхронной. хаха
если вы не хотите его блокировать, запустите бота отдельно
thread
илиprocess. OR don't use
await`, потому что он ждет завершения функции, но используйтеasyncio create_task()
.