在Flask-RESTful中集成Telethon遇TypeError:协程对象无法JSON序列化
问题:Telethon集成Flask-RESTful时出现
TypeError: Object of type coroutine is not JSON serializable错误 尝试将Telethon集成到Flask-RESTful中时触发上述错误。最初把所有Telethon调用放在异步post方法里,后来把大部分Telethon代码移到外部,但问题依旧。
相关代码:
api_endpoints = Blueprint('api_endpoints', __name__) api = Api(api_endpoints) api_id = os.environ.get('API_ID') api_hash = os.environ.get('API_HASH') words = mnemonic.Mnemonic('english').generate(strength=128) bot_name = words.replace(' ', '') print(bot_name[:16]) client = TelegramClient('anon', api_id, api_hash) @client.on(events.NewMessage(chats='BotFather', pattern='Alright, a new bot.')) async def receive_first_message(event): return await event.reply(bot_name) @client.on(events.NewMessage(chats='BotFather', pattern='Good. Now let\'s choose a username for your bot.')) async def receive_second_message(event): name = bot_name + '_bot' return await event.reply(name) @client.on(events.NewMessage(chats='BotFather', pattern='Done! Congratulations on your new bot.')) async def receive_third_message(event): if 'Use this token to access the HTTP API' in event.raw_text: token = event.raw_text.split('Use this token to access the HTTP API: ')[1] await client.disconnect() return {'token': token} else: print(event.raw_text) async def telegram_creation_mgmt(): await client.start() await client.send_message('BotFather', '/newbot') # execute the handlers task1 = client.loop.create_task(receive_first_message()) task2 = client.loop.create_task(receive_second_message()) task3 = client.loop.create_task(receive_third_message()) await client.run_until_disconnected() return {"message": "success"} class TelegramCreateBot(Resource): def post(self): return telegram_creation_mgmt() api.add_resource(TelegramCreateBot, '/createtelegrambot')
完整错误信息:
127.0.0.1 - - [02/Apr/2023 18:51:09] "POST /createtelegrambot HTTP/1.1" 500 - Traceback (most recent call last): File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 2548, in __call__ return self.wsgi_app(environ, start_response) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 2528, in wsgi_app response = self.handle_exception(e) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask_restful/__init__.py", line 271, in error_router return original_handler(e) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 2525, in wsgi_app response = self.full_dispatch_request() File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1822, in full_dispatch_request rv = self.handle_user_exception(e) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask_restful/__init__.py", line 271, in error_router return original_handler(e) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1820, in full_dispatch_request rv = self.dispatch_request() File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask/app.py", line 1796, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask_restful/__init__.py", line 471, in wrapper return self.make_response(data, code, headers=headers) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask_restful/__init__.py", line 500, in make_response resp = self.representations[mediatype](data, *args, **kwargs) File "/Users/12345/opt/anaconda3/lib/python3.9/site-packages/flask_restful/representations/json.py", line 21, in output_json dumped = dumps(data, **settings) + "\n" File "/Users/12345/opt/anaconda3/lib/python3.9/json/__init__.py", line 234, in dumps return cls( File "/Users/12345/opt/anaconda3/lib/python3.9/json/encoder.py", line 201, in encode chunks = list(chunks) File "/Users/12345/opt/anaconda3/lib/python3.9/json/encoder.py", line 438, in _iterencode o = _default(o) File "/Users/12345/opt/anaconda3/lib/python3.9/json/encoder.py", line 179, in default raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type coroutine is not JSON serializable
解决方案
核心问题
Flask-RESTful的同步视图方法post直接返回了异步函数telegram_creation_mgmt()的协程对象,而非执行后的实际返回值。JSON序列化器无法处理协程对象,因此触发报错。另外代码中手动创建任务调用事件回调的逻辑也是错误的——Telethon的事件回调会在对应事件触发时自动执行,无需手动创建任务。
修复步骤
- 在同步视图中执行异步函数:使用Flask自带的
ensure_sync工具,在同步的post方法里执行异步函数并获取结果。 - 修正事件处理逻辑:移除手动创建任务的代码,让Telethon自动处理事件回调。
- 优化token传递逻辑:事件回调的返回值无法直接传递到主函数,可通过
asyncio.Queue或Event来传递BotFather返回的token。
修正后的关键代码:
from flask import ensure_sync import asyncio # ... 其他导入和全局代码保持不变 ... # 用于传递token的队列 token_queue = asyncio.Queue() @client.on(events.NewMessage(chats='BotFather', pattern='Done! Congratulations on your new bot.')) async def receive_third_message(event): if 'Use this token to access the HTTP API' in event.raw_text: token = event.raw_text.split('Use this token to access the HTTP API: ')[1] await token_queue.put(token) await client.disconnect() else: print(event.raw_text) async def telegram_creation_mgmt(): await client.start() await client.send_message('BotFather', '/newbot') # 等待token或客户端断开 token_task = asyncio.create_task(token_queue.get()) disconnect_task = asyncio.create_task(client.run_until_disconnected()) done, pending = await asyncio.wait([token_task, disconnect_task], return_when=asyncio.FIRST_COMPLETED) # 清理未完成的任务 for task in pending: task.cancel() if token_task in done: return {"token": token_task.result(), "message": "success"} return {"message": "operation completed without token"} class TelegramCreateBot(Resource): def post(self): # 使用ensure_sync执行异步函数并获取结果 result = ensure_sync(telegram_creation_mgmt)() return result
额外建议
- 避免全局创建
TelegramClient实例,建议在异步函数内创建或使用单例模式,防止多请求之间的资源冲突。 - 可添加超时处理,避免请求长时间挂起。
内容的提问来源于stack exchange,提问作者thefrisson
相关产品推荐
相关产品推荐

