如何在异步任务完成时退出
How to exit when task is finished in asyncio
在这个简短和简化的代码中,我想等待所有任务完成(queue.join)然后离开。
此代码打开网络连接并下载一些数据。
不幸的是我必须推 'ctrl-c' 因为 'client.run_until_disconnected()'.
完整代码有效,但我不知道如何在不中断键盘的情况下退出。
我必须用 crontab 安排它,所以我不能使用 'client.run_until_disconnected()'
编辑:更新代码
#!/usr/bin/env python3.7
import asyncio
import telethon
from telethon import TelegramClient
from telethon import functions, types
from datetime import datetime
api_id = 00000 # your api_id
api_hash = "your api hash"
async def worker(queue):
while True:
queue_book = await queue.get()
book_name = queue_book.file.name
print(book_name)
loop = asyncio.get_event_loop()
await client.download_media(queue_book,book_name)
queue.task_done()
async def main():
#Free ebook medical articles
channel = await client(functions.messages.CheckChatInviteRequest('your channel hash'))
#values message's id depend on the chosen channel
ids = [63529,63528,63527,63526,63525,63524,63523,63522]
queue = asyncio.Queue(1)
workers = [asyncio.create_task(worker(queue)) for _ in range(5)]
for booksId in ids:
async for get_book in client.iter_messages(channel.chat, ids=booksId):
await queue.put(get_book)
await queue.join()
for the_worker in workers:
the_worker.cancel()
async def wait_until(dt):
now = datetime.now()
await asyncio.sleep((dt - now).total_seconds())
async def run_at(dt, coro):
await wait_until(dt)
return await coro
client = TelegramClient("Test", api_id, api_hash)
loop = asyncio.get_event_loop()
client.start()
try:
loop = loop.create_task(run_at(datetime(2021, 2, 19, 11,00),main()))
client.run_until_disconnected()
except KeyboardInterrupt as keyint:
print("KeyboardInterrupt..")
pass
run_until_disconnected()
只是一个辅助函数,如果您想控制事件循环何时结束,则没有义务 运行 它。最小的变化是将 client.run_until_disconnected()
替换为 loop.run_forever()
,并在 main()
结束时调用 loop.stop()
。
更惯用的方法是保持 main()
不变,而不是从 create_task
开始,await 从顶部开始-级别协程(通常按照惯例称为 main
,但您已经为其他函数选择了该名称)。然后就可以直接调用asyncio.run(actual_main())
,当main
结束时程序会自动退出。例如(未经测试):
# main and other functions as in the question
async def actual_main():
global client
client = TelegramClient("Test", api_id, api_hash)
await client.start()
await run_at(datetime(2021, 2, 19, 11, 00), main())
asyncio.run(actual_main())
在这个简短和简化的代码中,我想等待所有任务完成(queue.join)然后离开。 此代码打开网络连接并下载一些数据。 不幸的是我必须推 'ctrl-c' 因为 'client.run_until_disconnected()'.
完整代码有效,但我不知道如何在不中断键盘的情况下退出。 我必须用 crontab 安排它,所以我不能使用 'client.run_until_disconnected()'
编辑:更新代码
#!/usr/bin/env python3.7
import asyncio
import telethon
from telethon import TelegramClient
from telethon import functions, types
from datetime import datetime
api_id = 00000 # your api_id
api_hash = "your api hash"
async def worker(queue):
while True:
queue_book = await queue.get()
book_name = queue_book.file.name
print(book_name)
loop = asyncio.get_event_loop()
await client.download_media(queue_book,book_name)
queue.task_done()
async def main():
#Free ebook medical articles
channel = await client(functions.messages.CheckChatInviteRequest('your channel hash'))
#values message's id depend on the chosen channel
ids = [63529,63528,63527,63526,63525,63524,63523,63522]
queue = asyncio.Queue(1)
workers = [asyncio.create_task(worker(queue)) for _ in range(5)]
for booksId in ids:
async for get_book in client.iter_messages(channel.chat, ids=booksId):
await queue.put(get_book)
await queue.join()
for the_worker in workers:
the_worker.cancel()
async def wait_until(dt):
now = datetime.now()
await asyncio.sleep((dt - now).total_seconds())
async def run_at(dt, coro):
await wait_until(dt)
return await coro
client = TelegramClient("Test", api_id, api_hash)
loop = asyncio.get_event_loop()
client.start()
try:
loop = loop.create_task(run_at(datetime(2021, 2, 19, 11,00),main()))
client.run_until_disconnected()
except KeyboardInterrupt as keyint:
print("KeyboardInterrupt..")
pass
run_until_disconnected()
只是一个辅助函数,如果您想控制事件循环何时结束,则没有义务 运行 它。最小的变化是将 client.run_until_disconnected()
替换为 loop.run_forever()
,并在 main()
结束时调用 loop.stop()
。
更惯用的方法是保持 main()
不变,而不是从 create_task
开始,await 从顶部开始-级别协程(通常按照惯例称为 main
,但您已经为其他函数选择了该名称)。然后就可以直接调用asyncio.run(actual_main())
,当main
结束时程序会自动退出。例如(未经测试):
# main and other functions as in the question
async def actual_main():
global client
client = TelegramClient("Test", api_id, api_hash)
await client.start()
await run_at(datetime(2021, 2, 19, 11, 00), main())
asyncio.run(actual_main())