• Что то не то в скрипте?

    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)
    Ответ написан
  • Как всё таки работает асинхронность?

    Vindicar
    @Vindicar
    RTFM!
    Передразнивая одного человека, асинхронность это кооперативная многозадачность плюс цикл обработки событий.

    Упрощенно, есть набор функций, умеющих приостанавливать и возобновлять своё выполнение - корутин.
    Корутины обычно приостанавливают своё выполнение после запроса операции ввода/вывода, но могут и по другим поводам - например, просто ожидание, или ожидание завершения другой корутины, или ещё что.

    Ядром асинхронной программы является паттерн "реактор" - рабочий цикл. В контексте клиентского JS это рабочий цикл браузера, в контексте ноды - что-то отдельное, я полагаю (с нодой не работал).
    Цикл делает следующее:
    - ожидает завершения одной из операций ввода/вывода или ожидания (любой)
    - определяет, какая корутина ожидала эту операцию
    - передаёт ей управление
    - корутина делает своё дело, обрабатывая результат операции
    - потом корутина либо завершается, либо планирует еще одну операцию. И цикл возобновляется.

    Отсюда и вытекают все плюсы и минусы. С одной стороны, переключение между корутинами происходит в явно указанные моменты времени, так что меньше возни с синхронизацией.
    С другой стороны, длинные вычисления так не распараллелишь - только ввод/вывод. Ну или в длинном вычислении время от времени делать паузу, но выигрыша все равно не будет. Так что это имеет смысл только для IO-bound программ.
    Ответ написан
    3 комментария
  • Снижается версия Python почему?

    Vindicar
    @Vindicar
    RTFM!
    Нужно немножко включить голову и почитать про то, как работает SSH и оболочка Unix системы. Гуглинг типа "SSH keep program running" быстро бы вывел тебя на то что нужно.
    1. Когда ты подключаешься по SSH, сервер запускает копию bash или sh (или какая там оболочка используется) с правами твоего пользователя.
    <br>
    sshd<br>
      - bash<br>

    При вводе команды в этой оболочке программа ищется в системном PATH, а в нём находится второй питон.

    2. Потом, когда ты делаешь activate, ты переходишь в виртуальное окружение. Оно отличается тем, что питон там ищется по умолчанию другой, так как там поменян PATH (и ещё кое что). И происходит этот переход за счёт запуска дочерней командной оболочки.
    <br>
    sshd<br>
      - bash<br>
          - activate <br>
              - bash<br>


    3. Ты запускаешь свой скрипт. Он запускается из под оболочки внутри activate.
    <br>
    sshd<br>
      - bash<br>
          - activate<br>
              - bash<br>
                  - python3 your_script.py<br>


    4. Ты закрываешь putty. SSH сервер регистрирует отключение клиента, и посылает дочернему bash сигнал HUP - обычно он интерпретируется как сигнал на завершение. Тот передаёт этот сигнал своему дочернему процессу, и так далее.
    <br>
    sshd "sshd: эй, bash, завершайся"<br>
      - bash "bash: эй, activate, завершайся. А теперь я сам завершусь."<br>
          - activate "activate: эй, bash, завершайся. А теперь я сам завершусь"<br>
              - bash "bash: эй, python3, завершайся. А теперь я сам завершусь"<br>
                  - python3 your_script.py "python3: хорошо, завершаюсь."<br>

    В итоге получаем только работающий ssh сервер
    sshd
    И когда ты переоткрываешь сессию, activate уже перестал существовать, и ты снова попадаешь в обычный bash, где в PATH прописан только второй питон.

    Теперь главное: как же это обойти? Нужно сделать так, чтобы python3 проигнорировал сигнал о завершении. Есть несколько способов.
    Самый простой - использовать такой синтаксис:
    nohup python3 your_script.py &
    Амперсанд в конце означает "запусти программу и вернись в оболочку, не дожидаясь когда программа закончит работать". А команда nohup запускает указанную программу с указанными аргументами, но при этом она проигнорирует сигнал HUP, т.е. "эй, завершайся". А потому когда ты закроешь putty, бот должен остаться работать.
    Минус - после переподключения ты не будешь видеть вывод бота в консоль. Так что пиши логи!
    Чтобы остановить бота, придётся использовать ps чтобы узнать ID его процесса, и kill чтобы этот процесс прибить. Ну или можешь предусмотреть команду выхода в самом боте, которая завершит работу скрипта изнутри. Это удобнее.

    Второй способ - использовать программу screen, если она установлена. Документацию по ней гугли. Если коротко, screen позволяет создать виртуальную рабочую сессию, к которой можно подключатсья и отключаться, не прерывая её. При этом весь вывод на экран сохраняется между переподключениями. Удобно если бот пишет много в консоль, но несколько муторно, и надо учить сочетания клавиш.

    Третий способ - сделать так, чтобы бот запускался при загрузке, через init.d скрипт или systemd модуль. Но так как у тебя минимальные права, скорее всего это не прокатит.
    Ответ написан
    1 комментарий
  • Как написать функцию расшифровки этого алгоритма?

    Vindicar
    @Vindicar
    RTFM!
    А не факт что это вообще обратимо, так как при умножении на 31663 гарантированно произойдёт переполнение 16-разрядного целого, и старшие разряды будут потеряны.

    Можешь попробовать так, конечно: создай массив всех возможных 16-разрядных чисел: 0, 1, 2, ..., 65535.
    Затем каждый элемент этого массива зашифруй этим алгоритмом.
    Если в полученном массиве какие-то элементы повторяются, то полностью обратить операцию невозможно - только частично, только для уникальных элементов в массиве.
    Если же все элементы массива уникальны, то можно обратить операцию, просто определив индекс входной пары байт в этом массиве. Этот индекс и будет исходным значением. Тут уже есть простор для оптимизации.
    Ответ написан
  • Пишет лишнюю букву?

    Vindicar
    @Vindicar
    RTFM!
    А зачем тебе вообще цикл for i in password:?
    Если тебе нужно в консоль и в файл вывести одно и то же, то выполни F.write(f'{n} {password}\n') и всё.
    Ну и приём с with, который я показал в твоём предыдущем вопрос, тоже стоит применить.
    Ответ написан
  • Текст накладывается сам на себя?

    Vindicar
    @Vindicar
    RTFM!
    Добавлю, что
    F.close
    Не делает ровным счётом ничего, так как вы не вызываете метод close.
    Должно быть
    F.close()
    А ещё лучше заменить вот это:
    F = open("txt","w")
      for i in password:
        F.write(str(n)+ password + '\n')
        F.close

    На вот это
    with open("txt","w") as F:
        for i in password:
          F.write(str(n)+ password + '\n')
    Ответ написан
    Комментировать
  • Можно ли получить список пользователей дискорд через http url запрос?

    Vindicar
    @Vindicar
    RTFM!
    Не будучи на сервере - нет, насколько я знаю.
    Ответ написан
    Комментировать
  • Как сделать чат для трех и более компьютеров в python socket?

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

    Я бы посоветовал разобраться с asyncio, оно может сильно упростить написание сервера.
    Самое сложное будет написать клиента, так как нужно будет подружить asyncio с пользовательским интерфейсом клиента. Даже элементарный input() будет нетривиально использовать.
    Так что можно сразу использовать qasync, чтобы подружить pyqt и asyncio.
    Ответ написан
    Комментировать
  • Как обработать ошибку в discord.py, при неправильном заполнении типа данных?

    Vindicar
    @Vindicar
    RTFM!
    Используй обработчик ошибок, как показано тут. Будет что-то типа такого
    from discord.ext.commands import CommandError, ConversionError
    
    #обработчик команды
    @bot.command() 
    #черная магия discord.py анализирует type hints чтобы понять, как парсить входное сообщение
    async def plus(ctx, x: int, y: int): #указываем, что параметры команды - это целые числа
        z = x + y
        await ctx.send(f"{x} + {y} = {z}")
    #обработчик ошибки
    @plus.error
    async def plus_error(ctx, error):
        if isinstance(error, ConversionError):
            await ctx.send(f"Ошибка преобразования аргументов plus. Вы ввели не числа?")
        elif isinstance(error, CommandError):
            await ctx.send(f"Ошибка выполнения команды plus")
        else:
            await ctx.send(f"Неизвестная ошибка выполнения команды plus")
    Ответ написан
    Комментировать
  • Как изменить название кнопки с командой shell?

    Vindicar
    @Vindicar
    RTFM!
    smokedevil666, сделай глобальный словарь вида
    commands = { "Нажми": "python3 /foor/bar/baz" }
    И ищи в нём полученное сообщение. Если такого ключа нет, ругаешься на пользователя.
    Ответ написан
    8 комментариев
  • Почему выходит ошибка TypeError: list indices must be integers or slices, not str?

    Vindicar
    @Vindicar
    RTFM!
    А ты уверен, что в s1_json корневой элемент - словарь, а не список?
    Ну и то же самое про s_json.
    Ответ написан
    Комментировать
  • Почему в .exe файле программы (Pyqt5) не исполняются команды к sqlite3?

    Vindicar
    @Vindicar
    RTFM!
    > Таблица это сама есть, базу данных я перебросил в корень с исполняемым файлом.
    Т.е. ты не пытаешься запаковать БД, так?
    А ты уверен, что скрипт её находит? Указываешь полный путь до файла с БД? Или как всегда, относительный, и авось текущая рабочая директория будет правильной?
    Просто некоторые py -> exe упаковщики при запуске экзешника распаковывают скрипт во временный каталог, и работают оттуда... а тогда файл БД окажется не рядом со скриптом. Не помню, делает ли так py2exe, выясни.
    Ответ написан
    7 комментариев
  • Какие данные у потоков одного процесса общие?

    Vindicar
    @Vindicar
    RTFM!
    Кек, сам задавал такой вопрос сегодня на зачёте. Но время что-то не сходится.

    Общее:
    - Адресное пространство
    - - Как следствие, исполняемый код
    - - Как следствие, переменные окружения
    - Открытые дескрипторы

    Различается:
    - Стэк: у каждого потока свой, в одном адресном пространстве. но в разных его местах
    - Обработчики структурных исключений
    - Ну и вообще контекст потока: регистры процессора и т.п.
    Ответ написан
    3 комментария
  • Почему я получаю 'referenced before assignment'?

    Vindicar
    @Vindicar
    RTFM!
    Питон видит, что ты присваиваешь start_id что-то, и решает что это локальная переменная. А потом понимает, что ты выше её читаешь, и ругается. Это намеренное поведение, так как в противном случае либо:
    а) до присваивания бы читалось значение глобального start_id, а после - локального,
    б) глобальная переменная всегда изменялась бы вместо локальной, и появление новой глобальной переменной с тем же именем что и локальная где-то в функции приводило бы к её неожиданному изменению.
    И то и то неочевидно и могло бы привести к "молчаливому"(без исключений) но неправильному поведению программы.

    Если не присваивать, то локальной переменной start_id не существует, и чтение осуществляется из глобальной.

    Если так надо менять глобальную переменную, то явно пропиши её в начале функции как global start_id.
    А лучше не используй глобальные переменные без нужды. Если их более одной, стоит переделать это в класс.
    Ответ написан
    Комментировать
  • Обработка видео на пайтон. Соединить фото в видео. Как сделать?

    Vindicar
    @Vindicar
    RTFM!
    Ответ написан
    Комментировать
  • Как сделать рассылку сообщения сразу во все каналы?

    Vindicar
    @Vindicar
    RTFM!
    Как-то так. Никаких гарантий, что дискорд не пошлёт твоего бота далеко и надолго за спам.
    @client.command()
    async def test(ctx):
        await ctx.author.send(f'test')
        # сохраняем набор и порядок каналов на случай, если он поменяется в процессе отправки.
        channels = list(ctx.guild.text_channels)
        # формируем пачку корутин, выполняющих отправку
        send_coroutines = [channel.send('test') for channel in channels]
        # планируем одновременное выполнение этих корутин и ждём завершения. 
        # Исключения будут возвращены наравне с результатами, а не выброшены.
        results = await asyncio.gather(*send_coroutines, return_exceptions=True)
        # анализируем results на предмет ошибок. 
        # Успешная отправка вернёт объект сообщения, неудачная вернет (а не выбросит!) объект исключения.
        failed = [ (ch.name, str(res)) for res, ch in zip(results, channels) if isinstance(res, (Exception, asyncio.CancelledError)) ]
        if failed: # были ошибки?
            await ctx.author.send('Failed to send to the following channels:\n' + '\n'.join(f'- {ch}: {msg}' for ch, msg in failed))
        else: # ошибок не было
            await ctx.author.send('Message has been spammed successfully.')
    Ответ написан
    Комментировать
  • Как переделать условие на python 3.10?

    Vindicar
    @Vindicar
    RTFM!
    Дело не в версии питона, а в том что у тебя для первого i в i['key'] не содержится строка "full.zip". В этом случае питон 3.9 даст точно такую же ошибку, так как первый if не отработает, а второй обратится к time_create.
    А вот почему так - уже совсем другой вопрос. Может, разные пакеты установлены на двух версиях питона. Может, просто файлы в files_dict оказываются в немного разном порядке. Я бы посоветовал починить алгоритм в целом, т.е. инициализировать time_create каким-то значением до цикла.
    Ответ написан
    3 комментария
  • Python | Как получить общее количество пользователей в голосовых каналах моего Discord сервера?

    Vindicar
    @Vindicar
    RTFM!
    Как всегда, достаточно внимательно прочитать документацию.
    Guild.voice_channels: List[VoiceChannel]
    Т.е. это список, а ты дергаешь у него какие-то посторонние свойства.
    Вот у отдельного VoiceChannel и впрямь есть свойство members: List[Member].
    Как дальше, догадаешься?

    Что-то вроде
    sum(len(vc.members) for vc in member.guild.voice_channels)


    Этот подход удобен для инициализации количества участников при запуске бота.
    А вот для отслеживания можно не дергать вышеописанное каждый раз, а поступить иначе. Если before.channel is None, то человек вошел в войс-чат. Если after.channel is None, то человек вышел из войс-чата. Если ни тот ни другой, человек просто перешел из одного войс-канала в другой. Тогда хранишь количество юзеров, и делаешь ему +1/-1 согласно этим условиям.
    Ответ написан
    1 комментарий
  • Почему не работает запрос mysql?

    Vindicar
    @Vindicar
    RTFM!
    AlexSeley, засунь ошибку в автопереводчик, раз английского не знаешь.
    telebot пытается вызвать твою функцию start() с одним параметром, хотя с точки зрения питона она параметров не принимает.
    Mysql тут нипричем от слова совсем, можешь убедиться, заменив содержимое start() на pass.
    Так что вопрос "почему питон думает, что функция start() не принимает параметров".
    И вот тут уже нужен полный код бота. Оформленный как положено, а не просто копипаст.
    Ответ написан
    Комментировать