Задать вопрос
Ответы пользователя по тегу Python
  • Как исправить ошибку при использование requests python3?

    Vindicar
    @Vindicar
    RTFM!
    requests не умеет "догадываться" об используемом протоколе, это не браузер, который тупо подставлят https:// где надо и где не надо.
    Тебе придётся указывать протокол (либо https:// либо http://, зависит от ресурса) самому в начале запрашиваемой ссылки.
    Ответ написан
    Комментировать
  • Как создать окно с кнопкой Старт Стоп для данного кода?

    Vindicar
    @Vindicar
    RTFM!
    # if the 'q' key is pressed, stop the loop
    if key == ord("q"):
        break

    А зачем останавливать отладку, когда у тебя уже в коде есть выход по горячей клавише? Или код не твой, ты просто разместил объяву?
    А вообще GUI-средства cv2 нужны сугубо для отладки и для экспериментов, они мало подходят для написания сложного приложения. Так что если хочешь кнопки и поля ввода, придётся дружить cv2 с каким-то GUI-фреймворком.
    Ответ написан
    Комментировать
  • Как связать WEB UI с Python?

    Vindicar
    @Vindicar
    RTFM!
    Пусть Flask-приложение стартует первым и запускает твой worker-скрипт в отдельном процессе. Так они друг другу мешать не будут, и если твой worker вылетит, Flask выживет и сможет сообщить о случившемся (ну и перезапустить worker, если надо будет).
    Вопрос тут в выборе способа обмена данными между скриптом и Flask, а также между Flask и браузером.

    1. Worker -> Flask:
    - запуск worker через multiprocessing, обмен данными через очередь (multiprocessing.Queue).
    Плюс: возможен обмен простыми структурами данных, типа списков и кортежей.
    Минус: требует переделки скрипта-worker, чтобы вместо print() он отправлял данные в Queue, да и в целом его надо будет импортировать в Flask-приложение. Что-то кроме питона той же версии так не запустишь.
    - запуск worker через subprocess, обмен данными через перехват stdout.
    Плюс: worker остаётся без изменений, и может быть запущен отдельно. Строго говоря, любая консольная программа, не требующая ввода, может быть так запущена.
    Минус: обмен данными только как последовательность строк. Что-то другое потребует сериализации на стороне воркера, и десериализации на стороне Flask.

    2. Flask -> browser:
    - Самый простой и дубовый способ - long-running request.
    Твой обработчик запроса на Flask запускает воркера, но не закрывает соединение, а потихоньку читает поступающие от воркера данные и отдаёт клиенту. Проблема в том, что если клиент отрубился, восстановить соединение будет нельзя.
    - Чуточку более сложный - polling. Один обработчик запроса на Flask запускает воркера и всё. Другой обработчик пытается прочитать накопившиеся у воркера данные, и отдаёт их клиенту. Тогда на клиенте должен крутиться JS-скрипт, который будет периодически дергать второй обработчик. Проблема в том, что если данные от воркера долго не считываются (клиент отключился), очередь/pipe для связи между процессами переполнится, и воркер "подвиснет" на операции отдачи данных Flask. Также этот подход не будет работать с двумя и более клиентами.
    - Ещё более сложный, но надёжный - buffered polling. Данные от worker помещаются в какое-то хранилище (грубо говоря, в переменную). Хранилище может хранить как полную историю вывода, так и только последний полученный блок данных - смотря что тебе интересно. Тогда Flask-приложение должно отдельным потоком забирать данные у worker, и помещать их в хранилище. Основной поток будет обслуживать запросы, и отдельный обработчик запроса будет отдавать клиенту текущее состояние хранилища (целиком или последние изменения, смотря сколько хранишь).
    Плюс: такая схема будет работать при любом разумном числе клиентов, в том числе при нуле.
    Минус: доступ к хранилищу нужно аккуратно синхронизировать, например, с помощью threading.Lock().
    Ответ написан
    Комментировать
  • Почему не записываются данные в бд?

    Vindicar
    @Vindicar
    RTFM!
    def user_exists(self, user_id):
        with self.connection:
            ...
    def add_user(self, user_id):
        with self.connection:


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

    Vindicar
    @Vindicar
    RTFM!
    Вообще ответ зависит от конкретной задачи.
    У тебя преобразование каждого кусочка идёт независимо от остальных?
    Если да, то всё сильно упрощается. Опиши функцию вида:
    def process_one_part(part: numpy.ndarray) -> numpy.ndarray:
        ...

    Которая будет обрабатывать один фрагмент изображения.
    А дальше собрать их абсолютно тривиально, точно также, как ты их резал:
    # пустое изображение такого же размера, как исходное, с тремя каналами по 8 бит на канал
    # если на выходе у тебя другое число каналов или тип данных, поправишь
    result = numpy.zeros(image.shape[:2] + (3,), numpy.uint8)
    
    for i in range(img_h // bl_h):
      for j in range(img_w // bl_w):
        cropped = image[i*bl_h:(i+1)* bl_h, j*bl_w:(j+1)*bl_w]
        processed = process_one_part(cropped)
        # нужно, чтобы присваиваемый фрагмент имел такой же размер, как "окно" присваивания
        result[i*bl_h:(i+1)* bl_h, j*bl_w:(j+1)*bl_w] = processed
    # дальше делаешь с result что тебе нужно


    Ну и да... причём тут вообще имя?
    Ответ написан
  • Как правильнее всего разбить список?

    Vindicar
    @Vindicar
    RTFM!
    Ну для начала неплохо бы внятно описать, как задаются желаемые элементы.
    Если по индексам, то да, твоё решение через __getitem__() вполне работоспособно.
    import typing as t
    lst = ['a', 'b', 'c', 'd', 'e']  #  не называй переменную list
    
    def split(lst: t.List[t.Any], indices: t.Iterable[int]) -> t.Tuple[t.List[t.Any], t.List[t.Any]]:
        selected = list(map(lst.__getitem__, indices))
        remainder = list(lst)
        # удаляем с конца, чтобы еще не обработанные индексы не поехали
        # вот только с отрицательными индексами это уже не прокатит
        # их придётся самомму пересчитывать в положительные
        for i in sorted(indices, reverse=True):
            del remainder[i]
        return selected, remainder
    
    print(split(lst, [0, 3]))  # (['a', 'd'], ['b', 'c', 'e'])
    Ответ написан
    1 комментарий
  • Как в легенде диаграммы сделать один из элементов в конце списка?

    Vindicar
    @Vindicar
    RTFM!
    Сортируй без "Другие", а его добавляй уже после сортировки.
    Ответ написан
    Комментировать
  • Как вызвать файловый диалог Windows без сторонних библиотек (Python)?

    Vindicar
    @Vindicar
    RTFM!
    comdlg32.dll в помощь, в частности GetOpenFileNameA().
    Более новые диалоги используют Component Object Model для работы. Сразу скажу, мне доводилось общаться с COM-интерфейсами на чистом ctypes, и это тот ещё гемморой.
    Ответ написан
    Комментировать
  • Как в хендлер инлайн кнопки добавить значение, которое введёт пользователь?

    Vindicar
    @Vindicar
    RTFM!
    Не уверен, что у тебя за либа, но читай про state machine. Эта фишка есть во многих библиотеках для создания ботов.
    Ответ написан
  • Почему функция возвращает None?

    Vindicar
    @Vindicar
    RTFM!
    Ты в последней строке просто вызываешь sum(), но не возвращаешь значение.
    А функция, которая не возвращает значение явно, возвращает None.
    Ответ написан
    4 комментария
  • Как сделать так, что бы при нажатии на Button активировался CheckButton?

    Vindicar
    @Vindicar
    RTFM!
    Назначь but_5 обработчик клика, который сделает but_4.config(state='normal')
    И приучайся давать осмысленные имена переменным.
    Ответ написан
  • Как сохранять данные о поле в классе?

    Vindicar
    @Vindicar
    RTFM!
    Это у тебя просто класс с полем класса? Или это датакласс?
    Потому что у датаклассов можно прикрутить метаданные к полям, и потом извлечь их.

    Но вообще твоя задача достаточно просто решается "в лоб".
    class X:
        meta = {}
        a: int
        meta['a'] = {'foo': 'bar'}
    
    print(X.meta['a'])


    Да, можно замутить более хитрый синтаксис, вроде:
    class metadata(dict):
        pass
    
    class X(Metaclass):
        a: int = metadata(foo='bar')

    А потом описать класс Metaclass так, чтобы он находил поля с метаданными, и складывал их описания в одну структуру данных. По сути, dataclasses.field() примерно так и работает. Но честно, овчинка выделки не стоит. Слишком много мороки, а результат не сильно короче простого словаря.
    Ответ написан
    Комментировать
  • Почему у двух разных функций одинаковые ссылки?

    Vindicar
    @Vindicar
    RTFM!
    Распарси скобки в выводе корректно, и загадка исчезнет.
    <\bound method Aliases.new_alias of 
        <\aliases.py.Aliases object at 0x7fcf55c104c0>
    >

    Два разных метода одного объекта (с одним адресом).

    И да, имей ввиду, что если ты берешь адрес метода на экземпляре объекта - ты получаешь не адрес функции в классе, а адрес специального объекта-обёртки bound method, который эту функцию привязывает к конкретному экземпляру класса. Иными словами:
    import inspect
    
    class A:
        def test(self, x):
            print(x)
    
    a = A()
    print(A.test)  # <function A.test at 0x0000029692C0FB50>
    print(a.test)  # <bound method A.test of <__main__.A object at 0x0000029692BF3040>>
    print(inspect.signature(A.test))  # <Signature (self, x)>
    print(inspect.signature(a.test))  # <Signature (x)> так как значение self зафиксировано - это a
    # причём обёртка создаётся каждый раз новая, это НЕ один и тот же объект
    print(a.test is a.test)  # False
    # но две обёртки одного метода равны.
    print(a.test == a.test)  # True
    # а метод класса всегда один и тот же
    print(A.test is A.test)  # True
    print(A.test == A.test)  # True
    Ответ написан
    Комментировать
  • Почему бот дискорд не включается через heroku?

    Vindicar
    @Vindicar
    RTFM!
    А зачем ты импортируешь turtle? heroku не поддерживает графический интерфейс.
    2022-08-10T07:55:34.087638+00:00 app[worker.1]: File "/app/core/core.py", line 4, in
    2022-08-10T07:55:34.087730+00:00 app[worker.1]: from turtle import title
    Ответ написан
    Комментировать
  • Как написать исправить этот код?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых, обычно не имеет смысл объявлять функции из одного оператора, особенно если они вызываются лишь однажды. Это только усложняет код.
    Во-вторых, строка rub = 'рубль' or 'рублей' or 'рубля' не имеет ни смысла, ни эффекта. Просто убери её.
    В-третьих, чтобы определить последнюю цифру (две) достаточно операции деления с остатком на 10 (100). Делить число нацело не требуется.
    В-четвёртых, составь сначала алгоритм словами:
    если две последние цифры 11, 12, 13, 14 или последняя цифра 0, 5, 6, 7, 8, 9 - "рублей"
    иначе если последняя цифра 2, 3, 4 - "рубля",
    иначе - "рубль"

    Можно проверить вхождение значения в список так:
    if last_digit in (0, 5, 6, 7, 8, 9):
        ...

    Это удобнее, чем цепочка or.

    Дальше на питон перепишешь сам.
    Ответ написан
    5 комментариев
  • Почему не копируется список внутри класса?

    Vindicar
    @Vindicar
    RTFM!
    Запомни одну простую вещь: переменная в питоне - это просто ссылка, ярлык!
    Покажу на примере:
    a = [1, 2, 3]  # а содержит ссылку на некий список
    b = a  # b содержит ссылку на тот же список!
    print(b is a)  # True. b - это тот же объект, что и a
    a.append(4)  # Ссылка а не меняется, меняется объект по этой ссылке!
    print(a)  # [1, 2, 3, 4]
    print(b)  # [1, 2, 3, 4] так как b ссылается на то же, что и a
    a = [1, 2]  # теперь a хранит ссылку на другой объект-список!
    print(b is a)  # False. Даже если бы содержимое списков совпало, это два разных объекта.
    print(a)  # [1, 2]
    print(b)  # [1, 2, 3, 4] так как b хранит ссылку на старый список
    a.append(5)
    print(a)  # [1, 2, 5] изменили объект, на который ссылается a
    print(b)  # [1, 2, 3, 4] b ссылается на другой объект, он остался не изменён.


    Соответственно, у твоей проблемы есть четыре разных решения.
    1. Делай копию тогда, когда она тебе понадобится (т.е. тогда, когда в исходном списке уже лежат нужные значения). Не полагайся на то, что две доступные извне переменные всегда будут указывать на один и тот же список.
    2а. Не заменяй список на другой. Если ты хочешь заменить именно содержимое списка, а не заменять один объект-список на другой, можно написать так: a[:] = [1, 2, 3, 4] Для надёжности можешь этот список показать как read-only property вместо обычного поля класса - тогда можно будет модифицировать объект списка (добавлять/удалять элементы), но нельзя будет заменить список на другой.
    2б. Покажи наружу список как read-write property, при записи в property записывай список в обе переменные.
    3. Добавь в класс методы для управления элементами списка, сам список наружу не показывай.
    Ответ написан
    3 комментария
  • Как параллельно обрабатывать API запросы?

    Vindicar
    @Vindicar
    RTFM!
    Я бы сделал несколько по другому.
    Оформил бы отдельно рабочий поток/процесс, и заставил бы их общаться через пару очередей (классический паттерн producer-consumer). Подходящие классы очереди можно найти в multiprocessing (ну или в threading, если ты очень хочешь потоки вместо процессов).

    Основной (корневой) процесс запускает рабочие процессы, потом слушает входящие запросы. Получив запрос, кидает его в очередь. Первый свободный процесс извлекает запрос из очереди, обрабатывает, отправляет ответ на запрос, и снова ждёт появления элемента в очереди. Проблема в том, что при использовании процессов придётся передавать между ними сложный объект Request - я не уверен, что это будет просто. Можешь попробовать потоки, но в питоне потоки не всегда хорошо работают.

    Нужно будет подумать над тем, где будут узкие места. Я вижу два - собственно работа классификатора, и обмен данными с клиентами. Первое ты обходишь, второе можно отчасти обойти через асинхронную работу (flask это умеет).
    Ответ написан
  • Как изменять переменную из двух процессов?

    Vindicar
    @Vindicar
    RTFM!
    У тебя сначала self.storage.clear_text(), а потом print(self.storage.text). Это вообще какой смысл имеет?
    В итоге у тебя хоть что-то выведется только если звёзды сойдутся, и процесс-поставщик успеет засунуть свой контент в общую переменную в промежутке между этими вызовами.
    Защити общий ресурс мьютексом (Lock), чтобы гонки не было, и поправь порядок операций.

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

    Vindicar
    @Vindicar
    RTFM!
    Настрой свой редактор на отступ четырьмя пробелами и не путайся.
    Я навскидку вижу только это
    with open("citilink4.html") as file:
       src = file.read()

    Перед src явно три пробела.
    Ответ написан
    Комментировать