部署异步Telegram Bot:同时实现定时API请求与用户响应
我是Telegram Bot开发新手,这是我在Stack上的首个提问,若有不当之处请见谅。我正在使用aiogram库开发一款异步Telegram Bot,需求如下:
- 每小时向某API发起批量请求,将数据存储至Heroku PostgreSQL;
- 向所有用户发送从响应中提取的信息;
- 同时Bot需随时准备回复用户,目前仅实现消息回声功能。
完整代码可查看我的仓库:crypto-arbitrage-tgbot
代码结构说明
utils/db.py
定义BotDB类,通过insert_row()连接数据库并插入数据:
class BotDB: def __init__(self, db): self.db_connection = psycopg2.connect(db, sslmode='require') self.db_cursor = self.db_connection.cursor() def insert_row(self, row): self.db_cursor.execute("INSERT INTO events(timestamp, pair, sell_at, buy_at, sell_price_bid, buy_price_ask, sell_volume, buy_volume, profit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)") self.db_cursor.commit()
utils/parser_v3.py
定义继承自BotDB的类,通过get_pair()和execute_tasks()异步发起约120次API请求,获取响应后插入数据库;其中boot_up()和run_periodically()借助Periodic库实现定时任务:
async def boot_up(self): p = Periodic(self.interval, self.execute_tasks, self.pairs) await p.start() def run_periodically(self): loop = asyncio.get_event_loop() loop.create_task(self.boot_up()) loop.run_forever()
main.py
我认为问题出在这里,无法理解异步webhook函数与自定义异步函数如何协同,怀疑run_periodically()中的事件循环存在问题:
if __name__ == '__main__': logging.basicConfig(level=logging.INFO) start_webhook( dispatcher=dp, webhook_path=WEBHOOK_PATH, skip_updates=True, on_startup=on_startup, on_shutdown=on_shutdown, host=WEBAPP_HOST, port=WEBAPP_PORT, ) print('WEBHOOKED') parser.run_periodically() print('RAN 1 TIME, HOPE IT WORKS')
部署至Heroku后的结果
- Bot可正常回声用户消息;
- 但
run_periodically()无法启动,Heroku日志如下:
WEBHOOKED # 表明main.py中第一个函数执行成功
Traceback (most recent call last):
File "/app/main.py", line 67, in
parser.run_periodically()
File "/app/utils/parser_v3.py", line 58, in run_periodically
loop.create_task(self.boot_up())
File "/app/.heroku/python/lib/python3.10/asyncio/base_events.py", line 436, in create_task
self._check_closed()
File "/app/.heroku/python/lib/python3.10/asyncio/base_events.py", line 515, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
sys:1: RuntimeWarning: coroutine 'Parser.boot_up' was never awaited
我无法理解为何boot_up()从未被await,我认为已添加所有必要的await关键字,恳请各位提供修复方案或更优实现思路。
内容的提问来源于stack exchange,提问作者Dushamishkin

