Ответы пользователя по тегу Python
  • Как сделать проверку где писал user?

    Vindicar
    @Vindicar
    RTFM!
    В официальном FAQ есть же.
    How can I distinguish a User and a GroupChat in message.chat?
    Telegram Bot API support new type Chat for message.chat.
    Check the type attribute in Chat object:

    if message.chat.type == "private":
    	# private chat message
    
    if message.chat.type == "group":
    	# group chat message
    
    if message.chat.type == "supergroup":
    	# supergroup chat message
    
    if message.chat.type == "channel":
    	# channel message
    Ответ написан
  • Как написать распознавание капчи на python?

    Vindicar
    @Vindicar
    RTFM!
    1. Вырежи каждую цифру отдельно (содержащий прямоугольник).
    2. Нормализуй - переведи в оттенки серого (так проще сравнивать), приведи к какому-то фиксированному размеру.
    3. Сравнивай каждую цифру с эталонными изображениями цифр, прошедших такую же номрализацию. В качестве метрики возьми хотя бы расстояние L1 - т.е. вычитаешь значения попиксельно, берёшь модуль разностей (они могут быть меньше 0), и суммируешь.
    4. Эталон, который дал наименьшее значение метрики, наиболее похож.

    Для примитивной капчи, которая не содержит посторонних элементов и искажений, должно сработать.
    Ответ написан
    Комментировать
  • Как решить проблему с видимостью переменной root?

    Vindicar
    @Vindicar
    RTFM!
    @bot.message_handler(content_types=['text'])
    def get_command(message):
        if message.text == "Start":
          root = tk.Tk()
          img = ImageTk.PhotoImage(Image.open('lol.png'))
          createNewWindow(root, img)
          root.mainloop()
        elif message.text == "Stop":
          root.destroy()

    Ух как всё запущено.
    Во-первых, если ты ввёл Start, то get_command() создаёт локальную root, настраивает её, и уходит в бесконечный цикл внутри root.mainloop(). Я не знаю как pytelegrambotapi разруливает это, но бот после такого должен просто встать колом, пока все окна не будут закрыты. Подозреваю что обработчик вызывается в отдельном потоке, но фз. В любом случае, не надо так делать. Лучше иметь один root, который крутится внутри mainloop() в отдельном потоке всё время работы скрипта, а окна создавать и удалять по мере надобности, не создавая и не убивая root.
    Вообще подружить бота с оконным интерфейсом - задача нетривиальная.
    Во-вторых, переменная root - локальная. Она существует только внутри того экземпляра get_command(), который был вызван с командой старт. Если ты вызываешь его с командой Stop, у тебя запускается отдельный экземпляр, где выполняется только ветка Stop - а в этой ветке root объявлен не был, он был объявлен только в ветке Start, в другом экземпляре.
    В-третьих, окна будут спамиться только на той машине где запущен бот. Это так, на всякий случай.
    Ответ написан
    Комментировать
  • Как правильно реализовать систему непрочитанных сообщений в групповом чате?

    Vindicar
    @Vindicar
    RTFM!
    Ну например, для каждой пары пользователь-чат хранить метку времени отключения от чата (или эквивалентного события). Тогда все сообщения, которые были добавлены в чат после этой метки, будут считаться непрочитанными.
    Ответ написан
  • TypeError: descriptor 'append' for 'list' objects doesn't apply to a 'RetailItem' object?

    Vindicar
    @Vindicar
    RTFM!
    def purchase_item(self, self.__lst, obj): #приобрести товар

    1. Откуда вы вообще взяли такой синтаксис?
    2. У вас есть ссылка на self, по ней вы можете обратиться к любому атрибуту/методу self.
    Ответ написан
    3 комментария
  • Python cv2 как перести многомерный массив в картинку?

    Vindicar
    @Vindicar
    RTFM!
    src = [['255', '255', '255', '190', '190', '160', '76', '45', '78'],
    ['255', '255', '255', '190', '190', '160', '76', '45', '78'],
    ['255', '255', '255', '190', '190', '160', '76', '45', '78']]
    
    int_src = [ list(map(int, row)) for row in src ]
    red = [ row[0::3] for row in src ] #подразумеваю, что у тебя составляющие идут в порядке RGB
    green = [ row[1::3] for row in src ]
    blue = [ row[2::3] for row in src ]
    image = cv2.merge((blue, green, red)) #opencv по умолчанию хранит изображения в BGR, а не RGB
    Ответ написан
    Комментировать
  • Как выполняются декораторы в aiogram?

    Vindicar
    @Vindicar
    RTFM!
    Функции(как и методы) в питоне - это объекты первого рода, их можно сохранять в переменные, передавать как параметры и так далее. Соответственно, декоратор - это тоже функция, и тогда
    @decorator("params")
    def myfunc(func_params):
        pass

    это тоже, что и
    def myfunc(func_params):
        pass
    wrapper = decorator("params")
    myfunc = wrapper(myfunc)


    Никто не мешает decorator() и wrapper() в примере сохранять адрес оборачиваемой функции в какую-то структуру данных, используемую затем ботом для диспетчеризации поступающих событий. Пример без класса:
    registered_funcs = []
    
    def decorator(param):
      #вложенная функция - фактический декоратор
      def wrapper(func):
        global registered_funcs
        #запоминаем декорируемую функцию
        registered_funcs.append( (param, func) )
        return func #не забываем её вернуть
      #возвращаем wrapper, чтобы им можно было продекорировать целевую функцию
      return wrapper
    
    #пример использования декоратора
    @decorator("foo")
    def myfunc(x):
      print("Hello from myfunc(), ", x)
    
    print(registered_funcs)
    #>>> [ ("foo", <function myfunc at 0xdeadf00d>) ]
    #и мы можем этим списком пользоваться, например:
    for arg, func in registered_funcs:
      func(arg)
    Ответ написан
    1 комментарий
  • Как проводить тесты моделей, где в переопределенном .save() сохранение используется 2 раза?

    Vindicar
    @Vindicar
    RTFM!
    Ты в setUp() не очищаешь тестовую базу? Т.е. к моменту второго теста у тебя остаются данные после первого?
    Это плохая идея.
    Ответ написан
  • Как настроить logger python на запись LEVEL в разные файлы?

    Vindicar
    @Vindicar
    RTFM!
    нужно делать кастомный фильтр.
    Ответ написан
    Комментировать
  • Как реализовать разные скрипты Telegram bot'а в нескольких файлов?

    Vindicar
    @Vindicar
    RTFM!
    Проблема в том, что тебе нужно продекорировать функции через @bot.чтототам, но другие файлы ничего не знают о боте, так как он описан в главном файле. Так?
    Нужно учесть, как работает декоратор. Код вроде
    @bot.message_handler(commands=['anketaone'])
    def null_anketa_step(message):
        pass

    на самом деле работает примерно так:
    temp_wrapper = bot.message_handler(commands=['anketaone'])
    def null_anketa_step(message):
        pass
    null_anketa_step = temp_wrapper(null_anketa_step)

    Т.е. иными словами, декоратор - это просто вызов функции, в которую передаётся функция или класс!
    Тогда самый простой способ будет таким:
    def null_anketa_step(message):
        pass
    #какой-то другой обработчик
    def some_other_handler(message):
        pass
    
    def init_bot(bot):
        #а в этой функции мы регистрируем обработчики
        bot.message_handler(commands=['anketaone']) (null_anketa_step)
        #обрати внимание на две пары скобок. Вызов bot.message_handler() возвращает функцию (wrapper),
        #и мы эту функцию тут же вызываем, передавая в неё обработчик
        bot.message_handler(commands=['somethingelse']) (some_other_handler)

    Тогда в главном файле ты делаешь примерно так:
    bot = ........ #создаём бота
    from second_file import init_bot as init_second #импортируем второй файл
    #функцию импортируем под другим именем, чтобы не было коллизий между файлами
    init_second(bot) #вызываем функцию регистрации init_bot()
    
    if __name__=='__main__':
        bot.polling(none_stop=True)
    Ответ написан
    5 комментариев
  • Как найти объект по координатам в tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Всё что мне приходит в голову - перебрать все виджеты и найти те, чей прямоугольник содержит искомую точку.
    winfo_x()/winfo_y() - позиция виджета относительно родительского виджета.
    winfo_rootx()/winfo_rooty() - если не путаю, позиция виджета относительно начала экрана.
    winfo_width()/winfo_height() - текущий размер виджета
    winfo_children() - список дочерних виджетов для данного виджета.

    Но зачем тебе это понадобилось? Может, есть способ попроще?
    Ответ написан
    3 комментария
  • Как правильно прописать проверку ввода чисел на питоне для ТГ бота?

    Vindicar
    @Vindicar
    RTFM!
    try:
      v = int(message.text)
      #на случай если тебе подойдёт не всякое число
      if v < 0 or v > 99: 
        raise ValueError()
    except ValueError:
      bot.send_message(message.chat.id, "Не число, или недопустимое число.")
    else:
      bot.send_message(message.chat.id, f"Ты ввел число {v}")
    Ответ написан
    Комментировать
  • Аргумент пользователя в переменной?

    Vindicar
    @Vindicar
    RTFM!
    Если ссылка одна и кратковременная:
    current_url = None #храним ссылку в глобальной переменной
    @slash.slash(name = 'lastmap', description = 'последняя версия карты', options = [{"name": "ur", "description": "ссылка", "type": 3, "required": True}], guild_ids = [907669402181316638])
    @client.command(aliase = ['lastmap'])
    @commands.has_any_role(907669402181316638)
    async def lastmap(ctx, *, ur):
      global current_url
      id = ctx.author.display_name
      current_url = ur
      embedVar = discord.Embed(title="Карта", description=f"{id}, карта обновлена, ссылка: {current_url}")
      embedVar.set_image(url='https://media.discordapp.net/attachments/902258027648917524/907969211312271360/unknown.png')
      await ctx.send(embed=embedVar)    
    
    @slash.slash(name = 'map', description = 'последняя версия карты', options = [{"name": "text", "description": "текст", "type": 3, "required": True}], guild_ids = [907669402181316638])
    @client.command(aliase = ['map'])
    @commands.has_any_role(907669402181316638)
    async def map(ctx, *, text):
      global current_url
      id = ctx.author.display_name
      if current_url: #проверяем, задана ли карта
        embedVar = discord.Embed(title="Карта", description=f"Держи карту, {id}. Только зачем ты написал {text}?")
        embedVar.set_image(url=f'{current_url}')
        await ctx.send(embed=embedVar)
      else:
        await ctx.send(f"Извини, {id}, карта ещё не задана.")
    Ответ написан
    Комментировать
  • Как поставить скрипт на паузу в Python?

    Vindicar
    @Vindicar
    RTFM!
    > ввёл значение в поле input, а после нажатие кнопки "Подтвердить"
    1. Зависит от того, какой GUI фреймворк ты используешь.
    2. Зачем пауза, когда можно просто поместить нужные операции в реакцию на кнопку? Хотя, если тебе GUI нужен только для ввода данных, можно исхитриться - но тут уже см. п. 1.
    Ответ написан
    Комментировать
  • Почему не работает условие elif?

    Vindicar
    @Vindicar
    RTFM!
    Потому что если число больше 18, оно также больше 10.
    Ответ написан
    Комментировать
  • Почему не видит путь/экзешник?

    Vindicar
    @Vindicar
    RTFM!
    Юра Милевский, вынеси код ядра в отдельный поток (через threading) или в отдельный процесс (через multiprocessing). В главном потоке/процессе оставь GUI.
    Общение организуй через threading.Queue или multiprocessing.Queue (смотря что используешь).
    У тебя GUI задаёт только настройки ядра, ведь так? Тогда ты когда опльзователь что-то меняет в GUI, ты кладёшь в очередь кортеж вида ("имя параметра", "значение параметра"). Ядро в свободное время проверяет наличие новых элементов в Queue, извлекает эти кортежи, и запоминает новые настройки уже локально у себя (например, в словаре). Ну и использует этот словарь, когда потребуется.

    Если потребуется усложнить взаимодействие, то усложни структуру данных, которую передаешь. Например, кортеж будет иметь вид ("Имя команды", ["параметры", "команды"]). Ядро должно будет эту команду уже как-то интерпретировать и выполнить. Так или иначе, ключевая идея такая - передаёшь через очередь только примитивные типы вроде строк и чисел, а также кортежи, списки и словари.

    А если понадобится передать что-то от ядра в GUI, то используй отдельную очередь, которую GUI будет проверять, а ядро - наполнять.
    Ответ написан
  • Приветствую, пишу бота для дискорда на Python, не работает кик, в чем моя ошибка?

    Vindicar
    @Vindicar
    RTFM!
    lolikcheck09, кнопка </>

    Далее, я что-то не пойму с каким клиентом ты работаешь?
    Или ты работаешь с MyClient(), или ты работаешь с discord.ext.commands.Bot()?
    Потому что Bot() - это потомок Client(). Ты используешь его декоратор, т.е. опдписываешь свои функции на его события, но при этом не запускаешь bot, а запускаешь экземпляр MyClient().
    Ответ написан
  • Как реализовать выполнение процессов асинхронно?

    Vindicar
    @Vindicar
    RTFM!
    Ну если тебе нужна очередь, то asyncio.Queue в руки - или её эквивалент из threading, если решишь использовать потоки.
    Асинхронность поможет только если обработка элементов содержит большую долю ввода/вывода.
    Ответ написан
  • Как выполнять последовательную проверку данных в Google Seets?

    Vindicar
    @Vindicar
    RTFM!
    У меня получилось 4000 строк на 76 ключей

    Я надеюсь, вы знакомы с понятием цикла? o_O
    range='A3:A3',

    Просто генерируете значение range.
    for row in range(3, 130):
        values_guid = service.spreadsheets().values().get(
            spreadsheetId=spreadsheet_id,
            range=f'A{row}:A{row}',
            majorDimension='COLUMNS'
        ).execute()
        #ну и так далее

    Вместо цикла for по фиксированному диапазону можно сделать цикл while, и прерывать его когда наткнётесь на пустую ячейку. Тогда не придётся прописывать количество ячеек.
    Ответ написан
    3 комментария