Задать вопрос
Ответы пользователя по тегу Python
  • Как взять из массива все значения ключа?

    Vindicar
    @Vindicar
    RTFM!
    У тебя всегда в верхнем уровне массива один элемент?
    Ну так просто перебирай элементы в mas[0]['d']['x'].
    Если не всегда, то используй тот же цикл по z.
    Ответ написан
    Комментировать
  • Как переносить текст input() при ограничении количества букв?

    Vindicar
    @Vindicar
    RTFM!
    input() не предназначен для таких вещей.
    Тебе придётся или имитировать ввод вручную, или использовать модули для продвинутого консольного интерфейса типа curses (под винду нужно будет поставить пакет windows-curses).
    Ответ написан
    Комментировать
  • Как удалить символ из словаря?

    Vindicar
    @Vindicar
    RTFM!
    Включить голову и выучить уже стандартные структуры данных Питона.
    Вот кроме шуток
    Для начала, у тебя не словарь, а список словарей с разнообразными структурами данных внутри.
    А твой код пытается работать с этой структурой, как будто это список строк. Вот с чего ты взял, что это вообще сработает? Да ещё и используя регулярные выражения. Взял, что первой строкой в гугле попалось?


    Теперь скажи, в контексте вышесказанного - что значит "удалить символ подчеркивания"? Удалить откуда?
    Я предполагаю, что из значений в словарях внутри списка в ключе data для каждого словаря в твоем списке?
    Ну вот собственно эту фразу достаточно перевести на питон (от конца к началу), чтобы получить ответ.
    # этот код изменит твой массив "на месте", а не создаст изменённую копию!
    for mas_item in mas: # для каждого словаря в твоем списке
        for data_dict in mas_item['data']: # для каждого словаря в списке по ключу data 
            # словари не любят, когда их модифицируют и проходятся по ним for'ом одновременно
            data_dict_keys = list(data_dict.keys()) # так что заранее составляем список ключей словаря
            for key in data_dict_keys: # проходимся по этим ключам
                data_dict[key] = data_dict[key].replace('_', '') # и обрабатываем значения по этим ключам

    Как-то так. Чем тебе это подчеркивание помешало, без понятия.
    Ответ написан
    1 комментарий
  • Как отследить пользователей телеграм бота, написанного на python и где взять их Id?

    Vindicar
    @Vindicar
    RTFM!
    Выше уже ответили, что нужно регистрировать пользователей самостоятельно. Я опишу один из способов, как это сделать.
    Я предполагаю, что используется СУБД Sqlite, хотя это можно адаптировать и к другим.
    Нам потребуется таблица пользователей примерно такого вида:
    import time
    import sqlite
    
    connection = sqlite3.connect('bot.db')
    cursor = connection.cursor()
    cursor.execute("""CREATE TABLE IF NOT EXISTS users ( -- всё что после -- комментарий SQL
        id TEXT PRIMARY KEY, -- идентификатор пользователя, он же первичный ключ таблицы
        first_use REAL, -- метка времени, когда пользователь впервые обратился к боту
        last_use REAL -- метка времени, когда пользователь последний раз обратился к боту
    )""")
    cursor.close()

    То, что мы сделали id первичным ключом, гарантирует, что одному пользователю будет соответствовать только одна строка таблицы.
    Тогда перед выполнением каждой команды нужно обновить эту таблицу - добавить строку, если её нет, или обновить поле last_use, если она есть. К счастью, существует синтаксис, позволяющий сделать это за один запрос.
    def ensure_user_stats(user_id):
        "Эта функция обновляет таблицу users, и должна вызываться в начале обработки каждой команды."
        global connection
        cursor = connection.cursor()
        now = time.time()
        # пытаемся добавить строку с указанным id, и фиксируем текущее время в полях first_use и last_use 
        # если возникает конфликт в поле id (такое id уже есть),
        # то мы обновляем в этой записи поле last_use на текущее время, а остальное не трогаем
        cursor.execute("""INSERT INTO users (id, first_use, last_use) VALUES (?, ?, ?)
        ON CONFLICT (id) DO UPDATE SET last_use = excluded.last_use""", (user_id, now, now))
        cursor.close()
    Ответ написан
    Комментировать
  • Как использовать all/any с if?

    Vindicar
    @Vindicar
    RTFM!
    if any(x==item for item in ['fd', 'tf', 33]):
    Но это имеет смысл только если сравнение нетривиальное, и просто in не сработает.
    Ответ написан
    Комментировать
  • Как остановить поток при вводе команды?

    Vindicar
    @Vindicar
    RTFM!
    Единственный вменяемый способ - тело потока должно время от времени проверять какое-то условие (будь то объект threading.Event, или просто будевая переменная). Соответственно, если условие выполнилось, тело потока должно немедленно завершиться, не доделывая начатое.

    Если ты не контролируешь, что происходит в теле потока, и не можешь разделить его работу на отдельные мелкие итерации (чтобы в промежутке между ними проверять условие), то хорошего решения нет.
    Ответ написан
    Комментировать
  • Не могу понять в чем проблема?

    Vindicar
    @Vindicar
    RTFM!
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Вот это - трижды говнокод.
    1. Не засовывай в шаблонные строки ничего сложнее одной арфиметической операции - результат абсолютно нечитаем и неконтролируем (в чем ты убедился).
    Неправильно:
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]} :polegar_para_cima:**"""

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id)).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    2. Никогда не формируй запросы через форматирование строк. Слишком легко словить ошибку, явную или неявную.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = {}".format(ctx.author.id))

    Правильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) )

    3. Всегда проверяй, что ты получаешь из базы! Нет гарантий, что запись с указанным id и впрямь существует.
    Неправильно:
    score = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()[0]
    description = f"""У тебя , **{ctx.author}** вот столько балов!**{score} :polegar_para_cima:**"""

    Правильно:
    score_row = cursor.execute("SELECT cash FROM users WHERE id = ?", (ctx.author.id,) ).fetchone()
    if score_row is not None:
        description = f"""У тебя , **{ctx.author}** вот столько балов!**{score_row[0]} :polegar_para_cima:**"""
    else:
        # что делать, если такого юзера еще нет в базе?
        cursor.execute("INSERT INTO users (id, cash) VALUES (?, 0)", (ctx.author.id,) ) # можно его добавить
        description = f"""У тебя , **{ctx.author}** пока нет ничего! Но скоро будет!"""

    4. БаЛЛов, блин.
    Ответ написан
    5 комментариев
  • Как создать объект который самостоятельно распакуется в нужное число имен?

    Vindicar
    @Vindicar
    RTFM!
    Никак, слишком много значений для распаковки - это тоже плохо. А узнать количество распаковываемых переменных объект не сможет без анализа кода.

    Собственно, главный вопрос тут опять "а зачем тебе такое?"

    EDIT: Ну что ж, не говори, что тебя не предупреждали...

    # оба модуля - встроенные, а не сторонние
    import inspect
    import dis
    
    def callee(x):
        our_frame = inspect.currentframe()
        our_caller_frame = our_frame.f_back
        our_caller = our_caller_frame.f_code
        print(f"We are called by {our_caller.co_name}(), at line {our_caller_frame.f_lineno}")
        print("Our caller's code goes as following (byte string):")
        print(our_caller.co_code)
        bytecode = dis.Bytecode(our_caller, first_line=our_caller.co_firstlineno)
        print("Or, in human readable form, its this:")
        print(bytecode.dis())
        return [x*x]
    
    
    def caller():
        print("Calling callee()")
        y = callee(2)
        print(y)
    
    def other_caller():
        print("Calling callee()")
        z, *_ = callee(3)
        print(z)
    
    caller()
    other_caller()
    Ответ написан
    7 комментариев
  • Как подключить скрипт для определенного блока кода в пайтоне?

    Vindicar
    @Vindicar
    RTFM!
    Я исхожу из того, что ты можешь сопоставить пользователя, открывшего страницу, с пользователем, подписанным на твоего телеграм-бота. Надеюсь, ты в курсе, что боты ограничены в возможностях инициации контакта с пользователем - пользователь должен послать сообщение или войти в чат, где бот является админом.

    Я думаю, схема будет такая:
    1. При входе на целевую страницу, JS генерирует AJAX запрос с помощью fetch() или XMLHttpRequest, на твой выбор. Форму запроса (GET/POST) и передаваемые данные определяешь ты сам, но их должно быть достаточно для идентификации пользователя. В простейшем случае URL целевой страницы должен быть уникальным для каждого пользователя, и тогда можно будет передать этот уникальный идентификатор.
    2. Есть небольшой HTTP-сервер, который принимает эти запросы, записывает их в локальную базу данных и даёт отклик вида "успех/неудача". На чем он написан - неважно, но для простоты можно использовать Flask. Там будет строк 100 от силы. В качестве базы можно использовать sqlite.
    3. Есть Python бот, использующий одну из библиотек под телегу, который периодически смотрит в эту базу и проверяет наличие необслуженных запросов. Если таковые находятся, бот их перебирает, определяет для каждого запроса соответствующего пользователя, отправляет файл, и помечает запрос как обслуженный (ну или просто удаляет).
    61ceec5390670627570751.png

    Есть соблазн совместить пункты 2 и 3 в одном процессе, но это может оказаться нетривиально - тебе придётся крутить работу веб-сервера в главном потоке, а работу бота - в дополнительном. Тогда вместо базы данных можно будет использовать очередь (threading.Queue) - главный поток (Flask) кладёт задания в очередь, а поток бота - выбирает и обслуживает.
    61ceedcee35a5542427561.png
    Плюсы - один Python-скрипт вместо двух, отсутствие промежуточной БД.
    Минусы - повышенная сложность скрипта, при внезапной остановке скрипта текущие задания в очереди будут потеряны, труднее вести статистику обслуживания ботом пользователей.
    Решай сам, стоит ли оно того.
    Ответ написан
    7 комментариев
  • Сортировка словаря по нескольким значениям с условием по time.time()?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых, обычные словари сортировке не особенно поддаются. Порядок перебора ключей в словаре не определён, если я не путаю - нет гарантии, что на разных машинах, или на разных версиях питона, или даже при разных запусках скрипта порядок будет одним и тем же.
    Есть, правда, collections.OrderedDict - вот они запоминают порядок ключей, но это порядок всегда хронологический - самый поздний заданный ключ всегда будет последним при переборе.
    Во-вторых, лучше декомпозируй задачу на две. Сначала отфильтруй нужное, потом уже сортируй. Делать всё за один проход трудно, да и нужно ли?

    Я бы вообще посоветовал временно представить словарь как список кортежей (ключ, значение), и фильтровать/сортировать этот список.
    Ответ написан
  • Подскажете аналог set(), но для словаря?

    Vindicar
    @Vindicar
    RTFM!
    Даже не знаю с чего начать.
    Во-первых, массивы в питоне - это array, и они используются нечасто. Я сильно подозреваю, что ты имел ввиду списки (list).
    Во-вторых, set() к спискам отношения не имеет, это абсолютно самостоятельная структура данных - множество. От того, что есть идиома без_повторов = list(set(с_повторами)) set() не становится методом списка или чем-то подобным. Эта идиома прекрасно работает с любым коллекциями - списками, кортежами (tuple), да с чем угодно.
    В-третьих, повторы чего ты хочешь устранить? Ключей? Значений?
    Если ключей, то в словарях ключи и так не повторяются, как уже написали выше. Повторяющийся ключ просто заменит собой старый.
    Если значений, то тебе сначала придётся решить, какой из ключей с одинаковым значением сохранить.
    Ответ написан
    Комментировать
  • Как узнать индекс динамического виджета tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Есть два подхода. Один основан на лямбдах:
    for i in range(2):
        buttonFrame_update=Button(frame,text="Добавить", command= lambda arg=i: update_main_db(arg))

    Приём с аргументом лямбды необходим, чтобы сохранить текущее значение i - иначе в момент вызова лямбды она прочитает последнее значение i, а оно будет указывать на последнюю строку.

    Второй способ, которя я бы выбрал - написать свой виджет - строку таблицы. Тогда обработчик нажатия на кнопку сможет брать данные из экземплярной переменной.
    class MyTableRow(Frame):
        def __init__(self, master, *args, **kwargs):
            super().__init__(master, *args, **kwargs)
            self.widgets = []
            for i in range(3):
                widget = Entry(frame)
                widget.pack(side="left")
                self.widgets.append(widget)
            self.update_btn = Button(self, text = "Добавить", command = self.update_clicked)
            self.update_btn.pack(side="right")
            self.delete_btn = Button(self, text = "Удалить", command = self.delete_clicked)
            self.delete_btn.pack(side="right")
      
        def update_clicked(self):
            print(self.widgets[0].get())
        
        def delete_clicked(self):
            print("whatever")
    
    
    for i in range(2):
        item = MyTableRow(doth, borderwidth=2, relief="groove")
        frames.append(item)
        item.pack(side="top", fill="x")
    Ответ написан
    5 комментариев
  • Не свосем юзербот на discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Нельзя. И хорошо что нельзя.

    Можно подставить имя пользователя в начало текста, но всё равно будет видно, кто писал на самом деле.
    Ответ написан
    Комментировать
  • Защита софта на Python?

    Vindicar
    @Vindicar
    RTFM!
    Вопрос вообще "как идентифицировать компьютер". И это нетривиально.
    1. Получить MAC адрес сетевой карты и проверить его на вхождение в список. Простейший способ его получить - примерно такой:
    import uuid
    print(hex(uuid.getnode()))

    * неясно, как поведет себя функция, если на компе несколько сетевых адаптеров.
    * смена сетевой карты сломает программу
    * MAC адрес сетевой карты часто можно сменить
    2. Можно попробовать использовать CPUID, например, так.
    Но я без понятия, какие процессоры это поддерживают!
    3. Можно разместить секретное значение в реестре целевых машин, и проверять его наличие.

    Самая большая проблема - эту проверку может отломать любой, более-менее знакомый с языком.

    Можешь использовать пакет типа pyarmor, он вроде предоставляет механизм создания "лицензий" и обфусцирует исходный код, чтобы его труднее было анализировать и изменить. Но и pyarmor тоже отламывается при желании.

    Так что главный вопрос: а нафига?
    Ответ написан
    2 комментария
  • Как вывести все данные из БД?

    Vindicar
    @Vindicar
    RTFM!
    value, create = Choose.objects.get_or_create(voter=request.user)


    Может, поэтому?
    Ответ написан
    Комментировать
  • Хэш и соль пароля в файл?

    Vindicar
    @Vindicar
    RTFM!
    1. Читаешь из файла соль и хэш пароля.
    2. К введенному паролю добавляешь соль (так же, как она была добавлена к сохранённому) и хэшируешь.
    3. Сравниваешь два хэша - полученный и прочитанный. Если они совпали, пароль верен.
    Ответ написан
    2 комментария
  • Как переметить нулевые значения в конец списка?

    Vindicar
    @Vindicar
    RTFM!
    original_list = [0,1,8,3,0,4,5,0,0] #исходный список
    new_list = [x for x in original_list if x != 0] #только ненулевые элементы
    how_many_zeros =  len(original_list) - len(new_list) #сколько нулей потеряли?
    new_list.extend( [0] * how_many_zeros ) # добавляем нужное количество нулей в конец
    Ответ написан
    1 комментарий
  • Как еще чуть ускорить алгоритм?

    Vindicar
    @Vindicar
    RTFM!
    А не проще ли будет сделать в два прохода.
    Прямым проходом делаем так: если 0, то счетчик в ноль, иначе счетчик + 1 и элемент приравниваем счетчику.
    Потом то же самое делаем обратным проходом, но изменяем элемент только если он больше счетчика.
    Отсюда получаем:
    lst=[5, 3, 0, 2, 0, 3, 8, 2, 9, 7, 0, 0, 7, 1, 5, 3]
    L = len(lst)
    # если в начале списка не 0, то мы сможем задать корректные значения только на обратном ходе
    # так что ставим заведомо большее значение счетчика
    counter = len(lst) if lst[0] != 0 else 0
    for i in range(0, L):
      if lst[i] == 0:
        counter = 0
      else:
        counter += 1
        lst[i] = counter
    # обратный ход
    counter = lst[-1] - 1 #чтобы не запороть последние элементы
    for i in range(L-1, -1, -1):
      if lst[i] == 0:
        counter = 0
      else:
        counter += 1
        lst[i] = min(counter, lst[i])
    
    print(lst)
    # [2, 1, 0, 1, 0, 1, 2, 3, 2, 1, 0, 0, 1, 2, 3, 4]

    Правда, это даст некорректный результат, если список не содержит нулей. Но это можно обнаружить в ходе первого прохода.
    Ответ написан
    2 комментария
  • Что то не то в скрипте?

    Vindicar
    @Vindicar
    RTFM!
    Перечитывать файл каждый раз при обработке сообщения - не лучшая идея.

    Вместо этого сделай отдельную команду, которая будет его перечитывать.
    blacklist = []
    def load_stoplist():
        global blacklist #чтобы можно было изменить глобальную переменную
        inputfile = '1.txt'
        # учись как правильно работать с файлами
        with open(inputfile, mode='r', encoding='utf-8') as f:
            blacklist = list(map(str.strip, f.readlines()))
    
    @bot.message_handler(commands=['reload'])
    def reload_blacklist(message):
        #тут имеет смысл вставить проверку, чтобы бот игнорировал эту команду от других юзеров
        load_stoplist()
    
    #ну и так далее. А в конце скрипта
    if __name__ == "__main__":
        load_stoplist()
        bot.infinity_polling()
    Ответ написан
  • Discord.py кортеж и split,в чем проблема?

    Vindicar
    @Vindicar
    RTFM!
    Ты пытаешься сделать рандомный выбор из введённых значений?
    А на кой пельмень ты вообще соединяешь args? Если они разделяются пробелом, то так
    # команда вызывается как !choice вариант1 вариант_2 "вариант 3"
    @commands.command(pass_context=True)
    async def choice(self, ctx, *args:str):
      chosen = random.choice(args)

    А если прямо нужно через запятую, то лучше так:
    # команда вызывается как !choice вариант1, вариант 2, вариант 3
    @commands.command(pass_context=True)
    # discord.py интерпретирует * как "всю остальную строку засунь в следующий параметр" 
    async def choice(self, ctx, *, args:str): 
      choices = [arg.strip() for arg in args.split(',')]
      chosen = random.choice(choices)
    Ответ написан