• Можно использовать sqlite3 в асинхронном боте?

    @DollaR84
    Если ваша бд сильно нагружена, то действительно лучше использовать специализированные продукты типа postgres. Но в ином случае многие sqlite сильно недооценивают.
    Эта база может и простая, но имеет много возможностей, о которых большинство и не задумываются.
    Во первых, есть несколько вариантов указания работы с многопоточностью, указывается при сборке библиотеки, по умолчанию sqlite3.dll собрана с многопоточным доступом.
    https://www.sqlite.org/threadsafe.html
    Во вторых, у sqlite есть набор интересных ключей при открытии прагмы. Советую использовать, как минимум, journal_mode='wal'. Это освободит запросы чтения от ожидания завершения запросов записи.
    Также есть прагма threads, указывающая сколько лимитов потоков можно создавать, по умолчанию стоит 0, можно увеличить данное число.
    Со всеми прагмами можно ознакомиться тут: https://www.sqlite.org/pragma.html
    В третьих, если вы работаете с базой не напрямую запросами, а через какую-то ORM, то у них тоже могут быть дополнительные опции для потокобезопасности. Например, в простой ORM peewee при открытии базы, наряду с прагмами можно также указать флаг: thread_safe=True. Не разбирал подробности как он работает, но думаю он использует в своей работе ту же прагму threads.
    Поэтому все зависит от нагрузки и роли базы в ваших ботах. В некоторых задачах sqlite оправданный выбор. Надо подбирать инструмент под задачу.
    Ответ написан
  • Split строки и полученного массива на python?

    @dmtrrr
    Backend developer
    In [25]: s = 'BMW=X5,BMW=X1,Mercedes=G55,AUDI=A8,CHEVROLET=CRUZE'
    
    In [26]: dict([x.split("=") for x in s.split(",")])
    Out[26]: {'BMW': 'X1', 'Mercedes': 'G55', 'AUDI': 'A8', 'CHEVROLET': 'CRUZE'}
    Ответ написан
  • Bash scripts где смотреть исходники для практики?

    hottabxp
    @hottabxp
    Сначала мы жили бедно, а потом нас обокрали..
    Посмотрите скрипт автоматической установки OpenVPN - https://git.io/vpn
    Ответ написан
  • PhpStorm 2 окна как в subime3?

    delphinpro
    @delphinpro
    frontend developer
    Правый клик по вкладке - Разделить окно по вертикали (или горизонтали)

    20170124-205342.png
    Ответ написан
  • Как установить модули python без интернета и pip?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Kostyan4ik, почему это нет возможности? С питоном всегда можно найти какую-нибудь возможность.

    Вот, к примеру, вы можете на том компе, где есть питон и интернет, скачать все необходимые пакеты с помощью того же pip:
    pip download pip
    Так вы можете скачать все необходимые пакеты и принести их на машину без инета просто на флешке.
    А там:
    python pip-20.1.1-py2.py3-none-any.whl/pip install pip-20.1.1-py2.py3-none-any.whl

    Тут происходит маленькая магия: вы с помощью питона запускаете pip прямо изнутри локально лежащего файла с его дистрибутивом. Этим pip'ом вы ставите самого себя на локальную машину. Примерно как Барон Мюнхаузен, но не больно.

    Вы также можете сохранить перечень всех установленных пакетов на компе с инетом в текстовый файл, а потом, убрав из него лишнее, скачать все эти пакеты в локальный каталог, отнести на оффлайн-комп и там ставить через тот же pip
    pip freeze > r.txt
    pip download -r r.txt
    Ответ написан
  • Метод list() в Python возвращает непустой список. Почему так?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Типичная ошибка, которая рассматривается в каждом учебнике по питону.
    Во-первых, list - это не метод, а тип, который инстанцируется в список, если его вызвать.
    Во-вторых, вот в этой строчке def __init__(self, elements=list()): создаётся список. Он создаётся оин единственный раз при объявлении класса. Значение этого списка будет присвоено аргументу elements по умолчанию при каждом вызове конструктора без указания этого аргумента.
    То есть один и тот же список будет сохранён в атрибутах всех объектов этого типа, которые были инстанцированы без указания параметра.
    У всесх ваших таких экземплярах внутри ссылка на один и тот же список. Если через одну ссылку в список добавить элеенты, то через другую ссылку доступен тот е самый список с уже добавленными элементами.
    Ответ написан
  • Как сделать проверку на наличие определенного числа в базе данных (SQLite)?

    hottabxp
    @hottabxp Куратор тега Python
    Сначала мы жили бедно, а потом нас обокрали..
    Вот набросал вам самый простой код, поиграйтесь с ним. Тут нет ничего сложного:
    import sqlite3
    
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    
    name = input('Введите имя пользователя: ')
    
    cursor.execute('SELECT status FROM Users WHERE username = ?',(name,))
    
    result = cursor.fetchone()[0]
    if result == 3:
    	print('Вы администратор')
    else:
    	print('Вы обычный пользователь')

    Структура базы:
    5f849558dd33d864306206.png

    PS:
    Как сделать чтобы в базе искалось все таблицы где в status указано 3.
    у вас несколько таблиц? Зачем?
    Ответ написан
  • Альтернатива Excel для рисования таблиц?

    @Voland69
    gnuplot:
    есть обертка для python
    управляется командами - можно сделать все чего угодно
    можно выводить не на экран а в файл
    если подцепить python-docx то полученные картинки можно гнать сразу в документ

    если есть задача ко всему этому прикрутить GUI, то я бы предложил QML
    Ответ написан
  • Альтернатива Excel для рисования таблиц?

    @rostislav-zp
    может не совсем по теме,но этот урок мне очень помог(Рисуем графики Highcharts (Highstock) по данным из MySQL ) unboxit.ru/blog/63-risuem-grafiki-highcharts-highs...
    а вообще еще это прочитайте
    https://habr.com/ru/post/246907/
    Ответ написан
  • Можно ли использовать Raspberry Pi как небольшой домашний сервер для небольших задач?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Потянуть-то потянет, даже докер там развернёте. Но по памяти будет тесненько и ввод/вывод на флешку или что вы там подключите через USB будет довольно медленным.
    Но нафига вся эта машинерия - не ясно.
    Понятно, если бы мутили какой-нибудь умный дом и нужна локальная админка.
    Понятно, если на малинке поднять самопальный NAS (хотя медленный же...), понятно если торрентокачалку с DLNA, чтобы киношки через смарт-тв локально смотреть.

    Сервер на поиграться тоже можно, но сейчас VDS на лоу-костере обойдётся в 150-170р/мес (одно ядро, гиг оперативы и 20 гигов диска). При этом на ней белый айпишник, вы на ней поднимите в контейнерах VPN, телеграм-прокси, по ssh откуда угодно туда ходить можно и не возиться с NAT'ами домашнего провайдера.
    Занимаетесь вебом - иметь постоянную виртуалку для экспериментов, ИМХО, маст хев.
    Ответ написан
  • Как объединить два словаря?

    Как объединить два словаря?

    dict1 = {"a":"b"}
    dict2 = {"c":"d"}
    dict3 = {**dict1, **dict2}

    Результат:
    dict3 = {'a': 'b', 'c': 'd'}
    Ответ написан
  • Как осуществить связь счетчика RS485 с базой данных?

    Oxyd
    @Oxyd
    Linux enthusiast
    Да, есть интерфейсы проброса RS-232 / RS-485 по Ethernet. Самый известный производитель -- Moxa. Разумеется к одному порту 485 можно подключать несколько усройств. А вот, собственно, всякоразные конвертеры в Ethernet.
    Ответ написан
  • Как передать logging из импортированных модулей в основную программу?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Чтобы правильно использовать модуль logging, нужно во всех своих модулях содавать логгеры следующим образом:
    import logging
    log = logging.getLogger(__name__)

    В модулях, которые не запускаются сами по себе, никакого другого кода инициализации и настройки логирования не требуется.
    Если вы в своём модуле желаете различать два или более вида логов, то можно сделать как-то так:
    log = logging.getLogger(__name__)
    class MyModel:
        log = logging.getLogger(__name__ + '.MyModel')
        # ...

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

    В главном запускаемом файле кроме обычного создания логгера как во всех модулях будет ещё и инициализация и настройка системы логирования.
    В самом простом виде это что-то вроде такого:
    if __name__ == '__main__':
        logging.basicConfig(stream=sys.stderr, level='INFO', format='%(asctime)s %(levelname)-7s %(message)s')

    Тут говорится, что все логи уровня >= INFO будут в указанном формате направлены в stderr.

    В более сложном случае вы можете загрузить настройку логирования из конфигурационного файла или описать кодом:
    if __name__ == '__main__':
        # У вас может быть несколько разных способов форматировать код для разных мест:
        formatter_simple = Formatter(u'%(relativeCreated)08d %(levelname)-7s %(message)s')
        formatter_complex = Formatter(u'%(asctime)s %(levelname)-7s [%(filename)21s:%(lineno)-4d] %(message)s')
        # Несколько разных хендлеров для перехвата нужного вида сообщений и отправки в правильное место:
        handler_null      = logging.NullHandler()
        handler_screen    = handler(fmt=formatter_simple, stream=sys.stderr)
        handler_main_file = handler(
            fmt=formatter_complex,
            cls=logging.handlers.TimedRotatingFileHandler,
            when='midnight',
            backupCount=5,
            encoding='utf-8',
            filename=local_path('log/server.log'),
        )
        handler_errors_file = handler(
            fmt=formatter_complex,
            cls=logging.handlers.TimedRotatingFileHandler,
            when='midnight',
            backupCount=5,
            encoding='utf-8',
            filename=local_path('log/errors.log'),
            level='ERROR',
        )
        # А потом описываем сами логгеры:
        #   это корневой логер, пропускает все сообщения через себя насквозь и в то же отдаёт их своим хендлерам
        log_root       = logger(None, level='DEBUG', propagate=1, handlers=[handler_errors_file, handler_main_file, handler_screen])
        #   этот логер перехватывает логи торнадо-приложения, пропускает через себя и отдаёт хендлерам:
        log_app        = logger('tornado.application', level='DEBUG', propagate=1, handlers=[handler_errors_file, handler_main_file, handler_screen])
        #   этот собирает логи событий модели уровня выше или равного INFO (не отладочные) 
        #     и отдаёт соответствующим хендлерам, дальше для обработки свои сообщения не пускает
        log_events     = logger('app.model.events',     level='INFO',  propagate=0, handlers=[handler_errors_file, handler_events_file])
        #   этот логер съедает и отдаёт спец-хендлеру (он не показан выше, но должен быть) все логи http доступа
        log_websrv     = logger('tornado.access',                    level='DEBUG', propagate=0, handlers=[handler_websrv_file])
        #    этот логер глотает и гасит за ненадобностью все логи, которые генерит библиотека PIL при работе с PNG-файлами
        log_pil        = logger('PIL.PngImagePlugin',                level='INFO',  propagate=0, handlers=[handler_null])

    Если сообщение не перехвачено и не остановлено специфичным логером, оно улетает корневому логеру.
    Ну примерно как-то так.
    Само собой всю эту настройку лучше вынести в отдельный модуль и запускать при старте главного файла.
    Логеры вроде log_pil, log_websrv и прочих сохранены в отдельные переменные, но по факту в коде эти переменные нигде не используются. Их можно и не присваивать вовсе. В модуле логирования все логгеры регистрируются глобально в списке и поэтому в каждом модуле не требуется ничего импортировать, достаточно создать логгер по имени. По этому имени логер ищется среди созданных или автоматом создаётся новый. Имена логгеров используют точечную нотацию, и по ступеням имени их удобно фильтровать.

    Такой подход имеет свои недостатки (синглтон, неявное описание, толерантность к ошибкам), достоинства его весомы: отсутствие ада зависимостей (когда непросто или невозможно определить ациклический порядок создания логеров), гибкость настройки, изоляция (возможность перекрытия и фильтрации не влезая в код логирования).

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

    kshnkvn
    @kshnkvn Куратор тега Python
    yay ✌️ t.me/kshnkvn
    Ну если прям 100% всегда одинаковый вариант у всех дат, то можно и захардкодить:
    In [1]: from datetime import datetime
    
    In [2]: date_inp = 'Mon, 02 Mar 2020 13:30:00 +0300'
    
    In [3]: date_obj = datetime.strptime(date_inp, '%a, %d %b %Y %H:%M:%S %z')
    
    In [4]: date_outp = date_obj.strftime('%Y-%m-%d')
    
    In [5]: date_outp
    Out[5]: '2020-03-02'

    Ну лучше чет типа dateparser.
    Ответ написан
  • Где лучше всего пройти курсы по Python?

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

    @anerev
    Собрав самых известных хакеров континента все пришли к выводу что ваш код совершенен. Не хотели бы вы устроится в google ?
    Ответ написан
  • Как явно указать возвращаемый параметр?

    @bacon
    К сожалению, практика общения с автором, говорит что он дятел, поэтому наводящие вопросы ему не помогут, так что плачем и выдаем ответ
    antotherfunc(*equal())
    Ответ написан
  • Почему появляется ошибка permission denied?

    merryjane
    @merryjane
    Системный администратор
    Залогиньтесь под проблемным пользователем:
    su -l apache -s /bin/bash
    и проверьте руками есть ли у него права на чтение:
    cat /var/www/ssl/server.crt
    Ответ написан