Ответы пользователя по тегу Python
  • Почему файл сохраняется не по указанному пути?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Начинайте уже пользоваться современными удобными библиотеками для работы с путями:
    from pathlib import Path
    my_folder_path = Path('/home/pi/Desktop/bot2.0/photo')
    my_file_path = my_folder_path / 'my_file_name.ext'
    print(f'Для ясности можно залогировать путь по которому сохраняем: {my_file_path}')
    my_file_path.write_bytes(downloaded_file)
    Ответ написан
    Комментировать
  • Что значить pip install -e.?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Этот ключ означает, что пакет будет установлен в редактируемом режиме:

    -e, --editable Install a project in editable mode (i.e. setuptools "develop mode") from a local project path or a VCS url.

    Такое нужно, если мы хотим править исходники пакета, который устанавливаем.
    При этом пакет будет размещен не в обычный каталог site-packages, а в текущий или указанный каталог. Пути для поиска установленного пакета будут добавлены в переменную среды окружения и питон без труда найдёт установленную библиотеку не смотря на её необычное месторасположение.
    Найти это можно так:
    pip install --help
    Ответ написан
    Комментировать
  • Python Как сделать что бы программа не выходила после выполнения?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    from SimpleQIWI import *
    import sys
    
    # TODO: переименовать. Большими буквами именуются обычно константы.
    # здесь TOKEN лучше переименовать в token_file_name
    TOKEN = input('Введите путь к токену : ')
    PHONE = input('Введите номер телефона : ')
    
    # TODO: Обработать ошибку загрузки токена
    with open(TOKEN, 'r') as f:
        # TODO: переименовать. get_token - это плохое имя переменной 
        # для хранения токена. Лучше просто token или auth_token
        GET_TOKEN = f.readline()
    
    # TODO: Обработать ошибку некорректного/просроченного токена
    api = QApi(token=GET_TOKEN, phone=PHONE)
    
    while True:
        print('------------')
        print('[1] - Посмотреть баланс', '\n[2] - Отправить деньги', '\n[3] - Получить входящие платежи', '\n[4] - Выход')
    
        user = input()
    
        if user == '1':
          try:
            print('------------', '\nВаш баланс составляет : ' + str( api.balance ))
    
          except Exception:
            # TODO: Исследовать классы возможных ошибок 
            # и сделать целевые обработчики на уровне итерации цикла
            # чтобы не перегружать код этой обработкой
            print('Error\n' + str( sys.exc_info()[ 1 ] ))
    
        elif user == '2':
          print( '------------', '\n')
          # TODO: Сделать словарь с кэшем вводившихся ранее значений
          # чтобы не вводить повторно при ошибках
          payee_phone = input('Введите номер телефона получателя ( в международном формате + ) : ')
          payee_amount = input('Введите сумму перевода ( в рублях ) : ')
          payee_comment = input('Введите комментарий к переводу ( необязательно ) : ')
    
          try:
            api.pay(account=payee_phone, amount=payee_amount, comment=payee_comment)
    
          except Exception:
            print( 'Error\n' + str( sys.exc_info()[ 1 ] ) )
            print( '\nЕсли вы указали свой номер, то платеж будет невозможен!' ) 
    
        elif user == '3':
          print( '------------\n' )
          print( 'Функция временно не доступна' )
    
        elif user == '4':
          sys.exit()
    
        else:
          print( '\nТакого метода не существует!' )
    Ответ написан
    Комментировать
  • Как в Python отсортировать список по возрастанию?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Для конкретно вашего случая Maximxls привёл приемлемое решение.
    Я с похожей задачей сталкивался, когда делал CLI утилиту формирования плейлистов для аудиокниг.
    Там нужно было правильно отсортировать файлы с главами книги, при этом файлы пронумерованы, содержат текст, размещены в подкаталогах (тоже пронумерованных и с текстом).

    Имя каждого файла парсилось (разделялось) на составные части, и формировался ключ для сортировки вот такой вот функцией:
    def filename_key(fn: Path, root: Path = None) -> typing.Hashable:
        def split(s: str, re_splitter=re.compile(r'(\D+|\d+)')) -> tuple:
            return tuple(int(chunk) if chunk.isdigit() else chunk for chunk in re_splitter.split(s) if chunk)
    
        rel_path = fn.relative_to(root) if root else fn
        return tuple(split(name) for name in rel_path.parent.parts) + (split(rel_path.stem) + (rel_path.suffix,),)

    Можно применять так:
    my_files = (f for f in my_folder_path.rglob('*.mp3'))
    my_sorted_files = sorted((
        (filename_key(f, root=my_folder_path), f) 
        for f in my_files
    ))
    Ответ написан
    1 комментарий
  • Python диктофон. Как написать?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Там есть метод для прослушивания в фоновом режиме.
    import speech_recognition as sr
    from time import sleep
    import sys
    
    
    def on_listen(recognizer, audio):
        # print('on_listen')
        try:
            text = recognizer.recognize_google(audio, language='ru-RU').lower()
        except sr.UnknownValueError as e:
            pass
        else:
            print('Вы сказали:', text)
    
    
    r = sr.Recognizer()
    with sr.Microphone() as source:
        r.pause_threshold = 1
        print('Тихо...')
        r.adjust_for_ambient_noise(source, duration=1)
    
    print('Нажмите Enter для завершения')
    print('Говорите...')
    r.listen_in_background(sr.Microphone(), on_listen, phrase_time_limit=5)
    input()
    Ответ написан
    Комментировать
  • Для чего нужна функция ".union()" если можно сделать все намного короче и проще?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Дело в том, что это учебное задание, а оно направлено на обучение вас использованию множеств. Эту конкретную задачу можно решать как угодно, но в вашем случае вы, возможно, не освоите операций со множествами.

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

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Предлагаю вам накодить чего-нибудь на ~2000 строк и мы попробуем это отрефакторить=)
    Только делайте это в github, чтобы удобнее было делать ревью.
    Ответ написан
    Комментировать
  • Как красивее удалить N элемент из списка содержащего словари?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    mylist.remove(x)
    Удалит элемент по значению.
    Чтобы удалить по индексу нужно использовать метод `pop`:
    mylist=['a', 'b', 'c']
    mylist.pop(1)
    print(mylist)  # ['a', 'c']
    Ответ написан
    1 комментарий
  • Какую базу данных использовать для телеграмм-бота?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Всё зависит от того, какие задачи будут у вашего бота, какая будет у него архитектура, насколько сложные модели данных, собираетесь ли использовать ORM и какой именно.
    А может быть вам реляционная структура БД и вовсе не нужна и больше подойдёт NoSQL база данных.
    там их великое множество с разными возможностями и ограничениями от простых хранилищ ключ-значение, до развесистых и навороченных.

    Я бы порекомендовал MongoDB.
    Для питона есть огромное количество примеров и тьюториалов типа такого. Куда уж понятнее.

    С Монгой вы избежите необходимости возиться со схемой БД, можно избежать специфического процесса инициализации базы, создания ее структуры.
    Если данные, которыми будет оперировать ваш бот разнообразны, то неплохая идея написать модели в виде обычных питоновских классов, сделать методы сериализации (сохранения) в БД и десериалиации (загрузки) и забыть о базе как о какой-то отдельной сущности. Можно сконцентрироваться на логике работы.

    Вообще не очень понятна мотивация вашего вопроса. Сейчас полно простых доступных материалов по этой теме, в том числе на русском языке. А как выбрать какую БД использовать я вам уже описал. Для более детального совета не хватает информации о то, чем будет заниматься ваш бот.

    P.S.
    Прошу прощения за капитанские ссылки в тексте, но каков вопрос, таков и ответ.

    P.P.S.
    Должен признать, что я довольно предвзят в пользу монги. Скорее всего вам подойдёт всё что угодно.
    Меньше всего потребует настройки и знания, видимо, sqlite. Это embedded база данных, она заточена для простого использования. Однако если вам вдруг понадобится запускать несколько инстансов вашего бота, которые будут работать с одной БД, то посмотрите всё же в сторону MongoDB или Postgres. Mysql стал сдавать позиции и нет особых причин не использовать postgres, если вам нужна именно реляционная БД.
    Ответ написан
    Комментировать
  • Как запустить скрипт на python по URL?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Не очень хорошая идея запускать питоновский скрипт через CGI. При этом каждый раз запускается заново интерпретатор и такое решение не будет быстрым и эффективным.
    Вы могли бы воспользоваться каким-то микрофреймворком вроде flask или bottle, тогда питон будет запущен постоянно, фреймворк будет обрабатывать http запросы на своём порту, а апач вам нужно настроить так, чтобы он проксировал порт питоновского сервиса.

    Ещё можно покопаться в описании конфигурации апача и прописать там алиас урла, но это уже костыль, а раз уж вы взялись за костыли, то попробуйте просто переименовать свой скрипт `search.py` в `search.action`, а внутри первой строчкой пропишите шебанг вида: `#!/usr/bin/python3`
    Должно помочь. Я уже давно не пользуюсь апачем и не уверен, что он не смотрит по расширению чем запускать тот или иной срипт. В любом случае прописать правило по аналогии с тем, что там есть в конфиге по поводу `.py` скриптов будет не сложно. Пробуйте.
    Ответ написан
  • Python 3.8 Как правильно организовать сравнение?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вообще, так себе идея, конечно, у топик-стартера делать переменные динамически. Автор вопроса не знает наперёд сколько будет переменных, а значит вносит в программу неопределённость. Не понятно же есть та или иная переменная в конце-концов.

    Конечно за счет интроспекции и наделать переменных, и проверить их наличие можно безопасно, но это делает код плохо читаемым, провоцирует на трудно уловимые ошибки.

    Если автор вопроса настаивает, то может взять решение Drill и вынести содержимое словаря в локальный контекст:
    locals().update(var)
    locals().update(abc=123)  # создаст в локальном пространстве имён переменную `abc` со значением 123

    Но это плохо. Плохо делать такие вот переменные динамически.
    Опишите вашу задачу подробнее и конкретнее в этом или другом вопросе вам подскажут как правильнее решать такого рода задачи.
    Ответ написан
    Комментировать
  • Как замедлить часть проекта python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Не стесняйтесь заглядывать в исходники. В модуле threading, например, есть отдельный класс (наследник от Thread) для отложенного запуска функций. Вот его код полностью:
    class Timer(Thread):
        """Call a function after a specified number of seconds:
    
                t = Timer(30.0, f, args=None, kwargs=None)
                t.start()
                t.cancel()     # stop the timer's action if it's still waiting
    
        """
    
        def __init__(self, interval, function, args=None, kwargs=None):
            Thread.__init__(self)
            self.interval = interval
            self.function = function
            self.args = args if args is not None else []
            self.kwargs = kwargs if kwargs is not None else {}
            self.finished = Event()
    
        def cancel(self):
            """Stop the timer if it hasn't finished yet."""
            self.finished.set()
    
        def run(self):
            self.finished.wait(self.interval)
            if not self.finished.is_set():
                self.function(*self.args, **self.kwargs)
            self.finished.set()

    Собственно, это идеальное решение на чистых тредах.
    Если бы вы использовали, скажем, торнадо или aiohttp в качестве асинхронного фреймворка, то там уже есть готовый EventLoop и специальные методы для помещения в очередь задач, запланированных на запуск в конкретное время или через заданный интервал времени однократно или периодически.

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

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Прологируйте подробно вашу функцию и вы поймёте что больше тормозит.
    Основных проблемы может быть три:
    1) Долгий парсинг XML. Его время зависит от размера файла, а вставлять в базу вы начнете только по окончании парсинга. При этом весь файл в виде объектного дерева у вас будет в памяти. что может быть очень неэффективно.
    2) Долгий поиск нужных элементов в дереве. Это сомнительно, что он тут будет существенно тормозить на фоне прочих процессов.
    3) Долгая вставка из-за отдельных транзакций на каждую.

    1,2) Первая проблема может быть решена потоковым чтением XML через SAX-парсер. На закрытие определенных тегов вешаются события, а объект-парсер накапливает данные в своём состоянии. Это позволит получать данные по мере чтения и парсинга файла, а не после. Вторая проблема, кстати, то же решается sax-парсером. Просто не будет дополнительных накладных расходов на обход построенного парсером дерева.

    3) Можно попробовать cursor.executescript для пакетного исполнения запросов. Тут есть минус, нужно валидацию и экранирование данных делать руками и правильно. нужно бояться sql-инъекций.
    Лучше использовать cursor.executemany. Вот, например про это на стэковерфлов: https://stackoverflow.com/questions/18244565/how-c...
    Ответ написан
    Комментировать
  • Что это за инструкции выражений?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    2 + 2 писать без присвоения в отдельной строке смысла, конечно, нет. Результат не сохранится, а побочного эффекта это выражение не создаёт.
    Однако, вы могли, вызвать в выражении какую-то функцию с побочным эффектом.
    Строго говоря любой вызов функции в блоке кода в питоне является таким выражением, если её результат (а он есть всегда) не присваивается.
    Нужно быть аккуратным с побочными эффектами. Если вы зачем-то сделаете так:
    def my_global_effect_function():
        my_global_list.append('anything')
        return 3
    
    my_global_list = []
    my_global_effect_function() + 5

    Всё сработает, но никто не поймёт зачем вы все это делали
    Ответ написан
    1 комментарий
  • Логгирование Python, как быстро сделать вывод ошибок в файл?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Самое первое, что нужно делать в любом более-менее полезном скрипте или большой программе - это настроить логирование.
    В самом простейшем виде его можно устроить так:
    import sys
    import logging
    if __name__ == '__main__':
        log = logging.getLogger()
        log.level = logging.DEBUG
        log.addHandler(logging.StreamHandler(sys.stderr))
    else:
        log = logging.getLogger(__name__)
    
    ## Используем так:
    log.info('any text')
    log.debug('Something about %r in %s', log, __name__)
    
    ## Здесь размещаем весь остальной код
    if __name__ == '__main__':
        pass  # А здесь, если надо, размещаем то, что будет выполняться, когда модуль запускают как скрипт

    Тут всё логирование заворачивается в sys.stderr, не настроено форматирование, вывод в файл и ротация. Это минимальный уровень, дающий возможность отказаться от print для логирования.
    Пример для питона 2.7.
    Добавлю, что при непосредственном запуске этого кода логгер создаётся с именем по умолчанию (root). Это значит, что в других модулях проекта, управление которым передаётся,
    log = logging.getLogger(__name__)

    создаст логгер с именем модуля, и в главном файле можно будет настроить роутинг логов с учетом этих имён.
    Роутинг настраивается добавлением дополнительных хендлеров и к ним разных фильтров. Если есть какие-то затруднения с этим - пишите, поясню.
    Использовать правильное управляемое, расширяемое и гибкое логирование вместо россыпи принтов очень просто. Нужно просто себя приучить к этому, как к чему-то обязательному вроде чистки зубов, использования системы контроля версий и своевременного бэкапа.
    Ответ написан
    Комментировать
  • Как выбрать версию Python при установке пакета через pip?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    В общем нужно заускать пип через тот питон, к которому нужна либа. Попобуйте pip2 или посмотрите whereis pip и сделайте алиас на pip второго питона.
    Ответ написан
    Комментировать
  • Как перевести JSON в PythonObj без кракозябр?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Dmitry Azarenko привел отличный вариант.
    Ещё можно задампить d json с указанными вами параметрами то, что вы печатаете и напечатаь результат дампа, а не repr
    Ответ написан
    Комментировать
  • Как сформировать окрестность заданного метрического радиуса вокруг географически заданного центра в python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Что вы имеете в виду под "нормальным распределением в окрестности радиусом..."? Нормальное распределение задается мат-ожиданием (это у нас центр) и дисперсией. Это не значит, что наша случайная величина (точка) не выйдет за пределы этой вашей окружности, если под ее радиусом вы и понимаете дисперсию.
    А если нет, то правильно ли я понимаю, что вашу задачу можно переформулировать так:
    Получить случайную точку на геоиде с заданным мат-ожиданием и диспеорсией, которая (точка) лежит в заданном радиусе. То есть брать случайные точки по заданному закону распределения пока не встретится такая, которая внутри окружности?

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

    Питон тут ни при чем.
    Ответ написан
  • Как в python передавать аргументы в командной строке?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Статья в первом ответе, конечно, хорошая, но я бы посоветовал еще взглянуть на стороннюю библиотеку click для этих целей.
    pip install click
    Очень лаконичный и удобный подход (на мой взгляд) к вопросу.
    Ответ написан
    1 комментарий
  • Куда писать цифры что бы Python их посчитал?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Посмотрите внимательно на эти две строки:

    car = input ("Техническое обслуживанаие машины 'Ламборгини': ")
    rent = (input("Съем раскошной квартиры В Манхэттене: "))

    Первая сохраняет под именем car введённое пользователем значение, а вторая сохраняет туда кортеж с одним элументом -- введённым пользователем значением.
    При сложении кортежей они конкатенируются, что явно не требовалось в задании.
    Уберите лишние скобки.
    Ответ написан
    Комментировать