Используя библиотеку PyTelegramBotAPI я столкнулась с тем, что написанный мною бот работает мягко говоря не очень - когда ботом одновременно пользовалось несколько человек сообщения пересекались, записывались левые данные, да и вообще творилась какая-то вакханалия.
Хочу отметить, что я только начинаю свой путь и в данной статье по случайности могла написать какой-то бред, пожалуйста, не судите строго, если что - поправляйте)
Итак, предлагаю рассмотреть пример кода:
import telebot
bot = telebot.TeleBot('токен')
возможные состояния пользователя
@bot.message_handler(commands=['start'])
def hello_message(message):
id1 = message.from_user.id
bot.send_message(message.chat.id, f'Ваш id {id1}')
Здесь мы можем видеть небольшой кусок кода. Человек пишет команду /start и мы выдаем ему его id.
Вообще, этот кусок скорее всего будет работать без проблем, но если это всего лишь часть проекта, где нам нужно запомнить id и передавать его далее в другие функции, мы увидим проблемы.
Какие?
Представим ситуацию: два пользователя плюс минус в одно время нажали /start. Сначала код выполняется у первого и записывается его id, аналогично происходит и со вторым. В переменную id1 последним записался id второго пользователя, и да, самое главное - он будет доступен и будет пересекаться с другими пользователями! Функции доступны для взаимодействия для всех пользователей одинаково, и если один пользователь с нашей первой функции, рассмотренной в примере, переходит уже на следующую, куда будет передан его id, а потом второй пользователь перейдет в эту функцию, в конечном итоге запишется id второго пользователя! Это ужасно...)
Как же исправить этот недуг?
Я пять часов пыталась понять как исправить это, и знаете, все оказалось довольно таки просто. Вот новый, обновленный код:
import telebot
import random
bot = telebot.TeleBot('')
states = {} # словарь для хранения состояний пользователей
START = range(1) # возможные состояния пользователя
@bot.message_handler(commands=['start'])
def hello_message(message):
secret = 0
states[secret] = START
secret = random.randint(1,49494985894939494944)
states[secret] = START
id1 = message.from_user.id
bot.send_message(message.chat.id, f'Ваш id {id}')
Что же мы здесь видим?
Я добавила в этот код так скажем строки состояний. START = range(1) - это все возможные состояния пользователей - их может быть сколько угодно, в зависимости от функционала вашего бота и располагать их надо в каждой функции. Изначально был создан словарь states, он создавался вне всех функций. В первой функции, в самом ее начале, нам необходимо создать любую переменную (в нашем случае secret), и в эту переменную нужно записывать рандомное значение, которое не должно будет повторяться, затем передавать эту переменную далее в другие функции и аналогично писать в начале каждой функции states[secret] = (тут состояние пользователя). Я использую модуль random для генерации рандомного значения. Теперь при входе в функцию у каждого пользователя будет генерироваться свой, скажем, ключ идентификации, и другой пользователь не сможет получить доступ к этой функции.
Да, secret = 0
states[secret] = START
secret = random.randint(1,49494985894939494944)
states[secret] = STARTвыглядит странно, наверное, можно обойтись и без первых двух строчек, но я зачем-то, видимо на всякий случай, сделала так
Вообщем теперь ничего пересекаться не будет, после входа в каждую функцию у каждого пользователя будет генерироваться свой ключ, который далее будет передаваться в другие функции методом register_next_step_handler(), таким образом, наш бот получил режим многопользовательности:)
Спасибо за внимание) Надеюсь, кому-нибудь это поможет)
Комментарии (6)
wesp1nz
17.08.2024 11:38+1Не проще aiogram юзать? Ну а если код синхронный, то отдельный поток создавать)
d-sh
17.08.2024 11:38+1В первом примере кода никаких проблем не будет. Там локальная переменная id1 и она ни с кем пересекаться не будет. Она там вообще не нужна и по сути ничего не делает.
Во втором примере кода тоже самое + еще какие то ничего не делающие манипуляции.
kiff2007200
17.08.2024 11:38Так а у вас же уже есть уникальный id -
message.from_user.id
. Вы можете использовать его, а не генерировать новый с риском, что сгенерируется повторный. Также можно создать структуру, в которой хранятс id и другие данные пользователя, например состояния, и передавать эту структуру в следующие функции.
bagman2020
А рассматривали ли вы возможность использования более надежного способа хранения состояний пользователей, например, базы данных или системы кэширования, такой как Redis, вместо простого словаря? Я думаю это могло бы обеспечить большую масштабируемость и надежность, особенно если ваш бот должен обслуживать большое количество пользователей.