Я разрабатываю бота Telegram, используя библиотеку Telethon.
Я хочу передать значение tags_cv из send_tag_list() в show_selected_tags(). Но я получаю эту ошибку:
`ERROR - Unhandled exception on show_selected_tags
Traceback (most recent call last):
File "/home/kozorez/.cache/pypoetry/virtualenvs/content-telegram-bot-4LA9pChh-py3.10/lib/python3.10/site-packages/telethon/client/updates.py", line 570, in _dispatch_update
await callback(event)
File "/mnt/c/Users/kozor/PycharmProjects/content-telegram-bot/bot/bot.py", line 77, in show_selected_tags
some_var = tags_cv.get()
LookupError: <ContextVar name='tags' at 0x7f7e3e222de0>`
Я полагаю, что show_selected_tags() не получает значение tags_cv. Возможно, мероприятия Telethon проходят в разных асинхронных контекстах?
bot.py
"""Логика взаимодействия с ботом"""
import logging
import contextvars
from telethon.sync import TelegramClient, events
from services.channel import get_channel_data, add_channel_to_db
from services.post import parse_posts
from services.tag import get_tags_list
from services.keyboard import create_tags_keyboard
from config import (
api_id,
api_hash,
bot_token
)
bot = TelegramClient(
'bot',
api_id,
api_hash).start(bot_token=bot_token)
channel_data_cv = contextvars.ContextVar('channel_data')
tags_cv = contextvars.ContextVar('tags')
@bot.on(events.NewMessage(pattern='/start'))
async def send_welcome(event) -> None:
"""Отправка приветственного сообщения"""
await event.reply('Привет! Я — бот, который поможет тебе составить пост с навигацией по твоему телеграм-каналу. \
\nПросто пришли мне ссылку на свой телеграм-канал.')
@bot.on(events.NewMessage(pattern='https://t\.me/(\S+)'))
async def send_tag_list(event) -> None:
"""Анализируем посты из канала и возвращаем клавиатуру с тегами"""
channel_link = event.text
tags = None
try:
channel_data = await get_channel_data(channel_link)
channel_data_cv.set(channel_data)
except ValueError as error:
if 'Cannot get entity from a channel' in str(error):
await event.reply('Канал должен быть публичным')
logging.error(error)
try:
await add_channel_to_db(channel_data)
except Exception as error:
logging.error(error)
try:
await event.reply('Посты анализируются, ожидайте')
await parse_posts(channel_link, channel_data)
except ValueError as error:
logging.error(error)
await event.reply('К сожалению, мне не удалось найти ни одного тега')
try:
tags = await get_tags_list(channel_data)
tags_cv.set(tags)
except Exception as error:
logging.error(error)
tags_keyboard = await create_tags_keyboard(tags)
await event.respond("Выберите теги", buttons=tags_keyboard)
@bot.on(events.CallbackQuery())
async def show_selected_tags(event) -> None:
some_var = tags_cv.get()
print(some_var)
run.py
"""Запуск бота"""
import asyncio
import logging
from bot import bot
from db.models import *
from config import (
engine,
client
)
loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
async def init_db() -> None:
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.drop_all)
await conn.run_sync(Base.metadata.create_all)
logging.info('База данных инициализирована')
async def start() -> None:
await init_db()
async with bot:
await bot.run_until_disconnected()
logging.info('Бот запущен')
async with client:
await client.run_until_disconnected()
logging.info('Клиент запущен')
if __name__ == "__main__":
loop.create_task(start())
loop.run_forever()
Честно говоря, я не понимаю, как это исправить. Руководство по контекстным переменным слишком простое, чтобы ошибиться... Что еще, кроме контекстных переменных, можно использовать? Может кэширование?
Буду признателен за вашу помощь.






По умолчанию Telethon создает новую задачу для каждого обновления. Переменные контекста привязаны к контексту задачи. Если задача изменится, контекст изменится, и переменной у вас не будет.
В версии 1 вы можете включить sequential_updates, чтобы использовать одну задачу для всех обновлений:
client = TelegramClient(..., sequential_updates=True)
Это будет означать, что все обработчики обновлений используют одну и ту же задачу.
Обратите внимание, что задача отправки обновлений по-прежнему отделена от выполняемой «основной» задачи asyncio, поэтому, если вы хотите прочитать контекстную переменную из обработчика, она должна быть заранее установлена из другого обработчика.
Спасибо за объяснение. Я попробовал, но, к сожалению, все равно вижу ту же ошибку. Я использую Телетон 1.34.0.