Задать вопрос
  • Почему не работает семафор?

    Vindicar
    @Vindicar
    RTFM!
    Потому что процесс обращения к серверу разбит на две части.
    Одна - установка соединения, SSL-рукопожатие, формирование и отправка запроса, а также редиректы. Это - get()
    Вторая - загрузка и декодирование тела ответа. Это - text().
    Ты прячешь под семафор только вторую часть, но вполне возможно, что она занимает пренебрежимо мало времени по сравнению с первой. К слову, если хочешь ограничить одновременнные подключения к серверу, то точно нужно прятать под семафор первую часть тоже.
    Ответ написан
  • Как работает асинхронность в пайтон?

    Vindicar
    @Vindicar
    RTFM!
    asyncio - это, скорее, как обойтись без многопоточности.
    Она хорошо работает для ситуаций, когда большая часть времени потока выполнения уходит на ожидание ввода-вывода - например, на ответ по сети. Если у тебя есть что-то, что занимает CPU, или любая другая операция, выполняемая вне рамок ввода-вывода через asyncio - это остановит выполнение асинхронной программы.
    Если на пальцах, то асинхронная программа состоит из отдельных корутин. Разница с потоками в том, что потоки переключает ОС, а корутины сами отдают управление, когда уходят в ожидание события (грубо говоря, когда делают вызов с await). Это упрощает синхронизацию корутин, так как ты точно знаешь, когда твоя корутина отдаст управление - меньше шансов налететь на состояние гонки из-за внезапного переключения. Опять же, переключение корутин куда более детерминировано, чем переключение потоков, так что "плавающие" баги встречаются реже.
    Тело асинхронной программы - это рабочий цикл (т.н. реактор, он же loop), который проверяет выполняемые операции ввода-вывода, и возобновляет выполнение корутины, когда её операция завершилась. Когда корутина завершится или запланирует ещё одну операцию, она вернёт управление в цикл. Вот почему "задумавшаяся" корутина остановит всю программу.
    Минус в том, что в отличие от многопоточности, нельзя просто вжжжжжжух и сделать код асинхронным. Он должен писаться как асинхронный с самого начала, с прицелом на исполнение в реакторе.
    Ответ написан
    2 комментария
  • Как в функцию передать фильтр, сработавшего хендлера?

    Vindicar
    @Vindicar
    RTFM!
    Ну наверно посмотрить, что доступно в параметре state?
    Ответ написан
    Комментировать
  • Как добавить возможность передавать коду другие файлы и каталоги прямо в командной строке?

    Vindicar
    @Vindicar
    RTFM!
    " Ещё одним возможным улучшением была бы возможность передавать сценарию другие файлы и каталоги прямо в командной строке. Эти имена можно получать из списка sys.argv и добавлять к нашему списку source при помощи метода extend класса list."

    Выделение моё.

    А вообще, sys.argv хранит список параметров командной строки. 0й всегда содержит путь и имя исполняемого скрипта, а вот последующие задаются пользователем.
    В простых случаях можете просто работать с sys.argv как со списком, но если у вас что-то более сложное (типа необязательных аргументов), то смотри в сторону argparse.
    Ответ написан
    Комментировать
  • Ошибка TypeError: sequence item 0: expected str instance, dict found что делать?

    Vindicar
    @Vindicar
    RTFM!
    MyFile = open('C:\HP\proverka.txt', 'w')
    MyFile.writelines(persones)
    MyFile.close()

    writelines() ожидает получить на вход массив СТРОК, а ты даёшь массив словарей. Отсюда и ошибка.
    Зачем ты вообще этот фрагмент написал, если чуть дальше у тебя нормальное сохранение в json?
    Ответ написан
  • Есть ли коги или что-то им подобное в Telegram?

    Vindicar
    @Vindicar
    RTFM!
    Можно сделать самому.
    Смотри, ключевая возможность в большинстве библиотек для ботов - это регистрация реакции бота на события. И чаще всего она выполняется декоратором, типа @bot.command в discord.py или его эквивалент в aiogram.
    Но что такое декоратор? Если он не имеет параметров, то тогда
    @some_decorator
    def some_func():
        pass

    это то же самое, что и
    def some_func():
        pass
    some_func = some_decorator(some_func)

    Для декораторов с параметрами чуть-чуть сложнее
    @some_decorator(params)
    def some_func():
        pass

    превратится в
    def some_func():
        pass
    wrapper = some_decorator(params)
    some_func = wrapper(some_func)

    Отсюда вывод. Декоратор - это функция, и его можно сохранять в переменные, вызывать и так далее.
    Тогда можно сделать такой трюк: написать декоратор-прокси, который запоминает, что за метод мы декорируем, и чем. Примерно так:
    def proxy(storage, *args, **kwargs):
        def wrapper(func):
            storage.append((func.__name__, args, kwargs))
            return func
        return wrapper

    И применять его примерно так:
    class MyCustomCog:
        methods = []
        def __init__(self, bot):
            #задача конструктора - прочитать список отмеченных методов класса, 
            #и отдекорировать методы своего экземпляра класса (не одно и то же)
            for fn, args, kwargs in self.methods:
                #а тут вызываем декоратор вручную
                #что там вместо bot.event? можно сделать несколько прокси, или добавить еще один параметр
                decorator = bot.event(*args, **kwargs) 
                decorator(getattr(self, fn)) #теперь бот знает про наши обработчики событий
        #декоратор-прокси запоминает все декорированые методы в список methods
        #это можно реализовать и по другому, не суть. Главное, что мы запоминаем,
        #с какими параметрами потом вызывать декоратор реального бота - всё, что после methods
        @proxy(methods, "параметры", for="декоратора бота")
        async def some_handler(self, params):
            pass #обработчик того или иного события

    Эту логику можно спрятать в базовый класс, и наследоваться от него, чтоб не повторяться по сто раз. Да и сам proxy() можно сделать методом этого базового класса.
    Ответ написан
    1 комментарий
  • Как добавить словарь в файл через модуль pickle?

    Vindicar
    @Vindicar
    RTFM!
    Ну для начала я бы посоветовал использовать json вместо pickle. pickle даёт бинарную строку, которая нечитаема человеком. Кроме того, как написано большими красными буквами в доках на pickle, он имеет уязвимости, так что ни в коем случае нельзя передавать через него недоверенные данные.

    В коде много кривых вызовов не по делу.
    ff = open(file_name, 'rb')
    baza = {ff}

    Что сиё должно означать вообще? Ты создал множество из одного элемента - файлового объекта ff. Или ты ожидал, что это магически превратит файл в словарь?
    Как правильно:
    import json 
    #оператор with обеспечит закрытие файла, как только управление покинет тело оператора
    #явное указание кодировки подстрахует от получения "кракозябр" на выходе
    #Кодировка utf-8 позволит использовать символы любых алфавитов.
    with open('Список.txt', 'rt', encoding='utf-8') as ff:
        baza = json.load(ff)

    Далее.
    baza.update({users_name.title():users_numbe})
    Зачем? Почему не написать просто:
    baza[users_name.title()] = users_numbe
    Далее.
    f.close
    Ты взял адрес метода close у объекта f. Ты НЕ вызвал метод close. Чтобы метод вызвать, нужно указать круглые скобки. Впрочем, если используешь with, то он вызовет close() за тебя.
    Так что:
    with open('Список.txt', 'wt', encoding='utf-8') as ff:
        json.dump(
            baza, #что записываем
            ff, #куда
            ensure_ascii=False, #не ASCII-строки пишем как есть, без кодирования
            indent="    ", #сделать отступ, не писать всё в одну строку
            sort_keys=True, #отсортировать ключи по алфавиту
        )

    Остальное примерно так.
    Ответ написан
    Комментировать
  • Как создать напоминание в телеграм боте? Напоминалка каждый месяц?

    Vindicar
    @Vindicar
    RTFM!
    0. Ставишь aiogram и читаешь Quick start, чтобы понять, как в целом будет устроен бот.
    1. Создаёшь и ведёшь базу пользователей бота, например, в sqlite3. Как её наполнять, это уже второй вопрос. Также может потребоваться отдельная таблица напомнинаний, но тебе виднее что за напоминания будут.
    2. В боте создаёшь через asyncio.create_task() бесконечную задачу, которая
    - проверяет время
    - если сейчас подходящее время (скажем, полдень, 1е число месяца, плюс-минус 30 секунд), вызывает корутину уведомления пользователей,
    - засыпает на минуту с помощью await asyncio.sleep() (ни в коем случае не time.sleep()).
    3. Корутина уведомления пользователей должна извлекать из твоей базы уведомления, которые нужно отправить и id пользователей, которым эти уведомления нужно отправить (см. доки по sqlite3 как извлекать данные из БД запросом SELECT). Затем для каждого пользователя она должна отправить текст (см. доки по aiogram) и обработать возможное исключение (например, если пользователь заблокировал бота).
    4. Может потребоваться пара обработчиков команд, чтобы добавлять/менять текст напоминаний.
    Ответ написан
  • Как скачать архив по ssh?

    Vindicar
    @Vindicar
    RTFM!
    scp нужно запускать на своей машине. Например, так:
    scp user@server:/path_to_file/admin.2021-11-03_05-13-58.tar target_path/admin.2021-11-03_05-13-58.tar
    где user - имя пользователя,
    server - сервер, откуда качаешь файл.
    /path_to_file/ - полный путь к файлу
    target_path - путь на твоей машине куда качаешь файл.
    Это скачает файл с удалённой машины на твою. Если укажешь пользователя и сервер во втором параметре, то будет копировать с твоей машины на удалённую.
    Ответ написан
    4 комментария
  • Как это реализовать в discord.py?

    Vindicar
    @Vindicar
    RTFM!
    Ну простая же задача, на логику.
    У тебя при вводе команды отрабатывает функция Mishka(), а генерируешь случайный вариант ты вне её, один раз.
    Внеси случайную генерацию внутрь, и будет тебе счастье.
    Ответ написан
  • Что предпочтительнее - многопоточность или параллелизм (Python)?

    Vindicar
    @Vindicar
    RTFM!
    asyncio имеет удобный механизм асинхронного запуска задачи в отдельном процессе через run_in_executor(), так что это не такой уж жесткий выбор.

    Многопроцессность быстрее, но есть проблемы с передачей сложный объектов. По сути, можно отдавать туда и обратно только примитивы, словари и списки. Вещи типа массивов numpy приходится конвертировать.
    Так что если это не проблема - multiprocessing рулит.
    Ответ написан
    Комментировать
  • Как переместить все файлы в другую папку кроме папки с помощью терминала?

    Vindicar
    @Vindicar
    RTFM!
    Ну если тебе нужно перенести только файлы, но не трогать другие каталоги, то тогда можно попробовать
    mv /home/user/Videos/*.* /home/user/Videos/filters
    Так как у файлов обычно есть расширения.
    Ответ написан
    2 комментария
  • В чем принципиальная разница между идентифицирующей и неидентифицирующей связью?

    Vindicar
    @Vindicar
    RTFM!
    Ну, положим, они не полностью равносильны.
    В Phone_1 id должен быть уникален для каждой записи. Поэтому если ты захочишь переключить запись в Phone_1 с одного Employee на другого, ты точно всегда сможешь это сделать. Это можно интерпретировать как "записи в Phone_1 существуют сами по себе, несмотря на обязательную связь с Employee".
    В Phone_2 id должен быть уникален среди записей с одинаковым Employee_id. Т.е. уникальной должна быть их комбинация. При попытке переключения записи в Phone_2 с одного Employee на другого Employee есть риск коллизии по id. Это можно интерпретировать как "записи в Phone_1 существуют строго в контексте Employee, и их собственные id имеют смысл только в контексте, заданном Employee_id". Т.е. Employee_id становится своего рода "пространством имён".
    Ответ написан
    2 комментария
  • Как перенести данные из динамических инпутов в базу данных?

    Vindicar
    @Vindicar
    RTFM!
    чтобы django просмотрел всю страницу

    Ну для начала хочу убедиться: ты понимаешь разницу между кодом на сервере и кодом на клиенте?
    На случай если нет

    Цепочка обычно такая:
    1. Клиент посылает запрос, в том числе при переходе по ссылке
    2. Сервер генерирует страницу (тут работает питон), которая может включать в себя JS код.
    3. Сервер отправляет страницу клиенту. Начиная с этого момента Питон не может ничего сделать.
    4. Клиент разбирает страницу и выполняет JS код.
    5. JS код может выполнить еще один запрос к серверу.

    Так что не "пусть django просмотрит страницу", а "JS код на странице должен сформировать фоновый (AJAX) запрос к отдельному URL, в теле которого передать на сервер содержимое таблицы. Обработчик этого URL на стороне сервера должен принять тело запроса, валидировать полученные данные и поместить их в таблицу".
    Тогда задача разбивается на несколько типовых подзадач:
    1. Отправка AJAX-запроса на JS по нажатию кнопки на странице (гуглится).
    2. Отправка AJAX-запроса с телом (гуглится, смотри документацию по JS).
    3. Приём тела запроса в Django (гуглится, смотри документацию по Django).
    4. Превращение тела запроса в структуру данных, удобную для тебя (должен сделать ты). Можно передавать JSON, его легко формировать через JS и легко читать Питоном. Например, список из объектов, где каждый объект - это одна строка таблицы, а поля объекта - значения колонок.
    5. Перебор элементов в структуре и их валидация. Делаешь ты, так как только ты знаешь, какие данные передаются.
    6. Для валидных данных - добавление в таблицу БД (гуглится, смотри документацию по модулю sqlite3).

    Если возникнут вопросы по конкретной подзадаче, задавай их отдельно.
    Ответ написан
    Комментировать
  • В чем ошибка условия if?

    Vindicar
    @Vindicar
    RTFM!
    Ты не указал тип arg, поэтому discord.py оставляет его строкой. А "1" (строка) не равна 1 (числу).
    У discord.py есть удобная фишка - если указать в обработчике события параметры и подсказку типа для них, библиотека попытается разобрать введенную пользователем строку на эти параметры, и привести их к нужному типу. Так что напиши что-то типа
    async def test(ctx, arg: int):
    Ответ написан
    Комментировать
  • Как сделать последовательную проверку?

    Vindicar
    @Vindicar
    RTFM!
    Не пиши простыню кода, а разбей задачу на составляющие.
    Для начала отрефактори(переделай) свой код в функцию такого вида:
    def is_guid_accepted(guid: str) -> bool:
        #тут код

    Т.е. функция, которая принимает GUID и возвращает либо True (подтверждён), либо False (не подтверждён). При ошибке можешь выбрасывать исключение, или тоже возвращать False.

    После этого задача упростится.
    1. Прочитать содержимое .xlsx файла, если так уж хочется эксель (а может, всё же csv? будет проще), вытащить из него список GUID'ов и task_id. Гуглится.
    2. Для каждого GUID в списке вызвать функцию выше.
    3. Если функция вернула True, то добавить task_id в список успешных.
    4. Для каждого task_id в списке успешных отправить оповещение. Тебе виднее, как.
    Ответ написан
    1 комментарий
  • Почему телеграм бот долго реагирует на команды?

    Vindicar
    @Vindicar
    RTFM!
    async with pool.acquire() as conn:
    async with conn.cursor() as cursor:

    Как по вашему, что делают эти строки?
    Такое ощущение, что он каждый раз подключается к бд, прежде чем выдать ответ.
    Ответ написан