• Какие есть инструменты для markdown?

    eduardtibet
    @eduardtibet
    Technical Writer / Documentation Engineer
    Если вам именно Маркдаун, посмотрите на проект Фолиант: https://github.com/foliant-docs/foliant
    Ответ написан
    1 комментарий
  • Как передать 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 в именовании файлов проекта. Не смотря на то, что негласное это правило часто нарушается даже популярными библиотеками, всё же это часто создаёт лишнюю неразбериху и проблемы.
    В частности много геморроя можно поиметь переименовав файл сменив лишь регистр символа под контролем версий при работе с репозиторием на разных файловых системах. В винде, к примеру, регистр в именах сохраняется, но системой не различается, а в линукс различается. Таким образом винда не увидит переименования, а линукс увидит. Это может породить адский треш.
    Ответ написан
    Комментировать
  • Почему ВКонтакте не подцепляет мой OpenGraph image?

    hayk
    @hayk
    Как уже написали, скорее всего закешиловалось. Убедиться просто: добавьте гет-пареметр в урл.
    Ответ написан
    3 комментария
  • Как сделать таймер в python?

    kshnkvn
    @kshnkvn
    yay ✌️ t.me/kshnkvn
    Тебе нужно использовать любую базу данных. Принцип такой:
    При обращении любого пользователя к боту его ID записывается в БД, как только он получает нужную информацию в таблицу записывается, например time.time() и каждый раз при обращении пользователя к боту происходит примерно такая проверка:
    if (time.time() - last_update) >= 86400:
        print('Ты снова можешь получить подарок:)')
    else:
        print('Ты уже получал подарок')

    Для таких целей подойдет любая БД, можешь попробовать SQLite - она очень простая.
    Ответ написан
    4 комментария
  • Как у вас происходило обучение python?

    NeiroNx
    @NeiroNx
    Программист
    Для начала вам нужно научиться формализовывать задачу: представить что такое "Контакт" - это "Фамилия, Имя, Отчество, email,телефон", потом представить что такое сохранение на диске - это некоторый файл в котором куча контактов - например каждая строчка это отдельный контакт - в итоге получается формат хранения CSV(поля разделенные запятыми).

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

    Потом вы уже можете гуглить - "python работа с файлами" или читать конкретную главу справочной информации.
    А со временем вы уже запомните эти примеры и гуглить придется меньше.

    Обучение конкретно python сводится к запоминанию(пониманию) примеров решения конкретных мини-задач, как работа с файлами, работа с базами, работа с сетью, работа с GUI - разбивается на работу с каждой графической библиотекой которых куча GTK,Qt,wX,Tk,Kivy.
    Ответ написан
    Комментировать
  • Головоломки помогают айтишникам улучшить мышление?

    search
    @search
    мама говорит что я особенный
    Головоломки по программированию очень неплохо помогают устроиться на нормальную работу.

    Оффтоп, лет 5 назад научился жонглировать. Может это накрут, но заметил как сильно выросла способность концентрироваться. Гораздо дольше могу удерживать внимание на предмете/задаче чем раньше. Вот например сейчас одновременно пишу этот комментарий, пишу код и еще и жонглирую.
    Ответ написан
    2 комментария
  • Что с переводом идентификаторов?

    Beshere
    @Beshere
    Разработчик
    Пришел к тому, что лучше делать переменные из двух слов, пусть даже обрезанных. Пусть оно длиннее, но в итоге не запутаешься , если вдруг возникает новая сущность с таким же названием, и больше вариантов с тем же словарным запасом.

    Например, тогда бы вам не пришлось отказываться от ёмкого слова Fan: fanIn, fanOut, лучше чем Supply и Exhaust.
    Ответ написан
    1 комментарий
  • Что с переводом идентификаторов?

    Adamos
    @Adamos
    Вот тут часто спрашивают - а нужно ли программисту высшее образование?
    Так вот, на нашем строительном факультете половина курса английского была таки заучиванием терминов по словарю.
    Транслит ужасен как в том, что плодит ошибки при написании, так и в том, что вынуждает читающего постоянно "переключать контекст" с языка программирования на русский, да еще вычитывать дикие конструкции типа borzhch вместо беглого чтения.
    Вы можете довольно вольно использовать неточные слова и откровенный пиджин - главное, чтобы вы понимали написанное без вглядывания и человек, который читает ваш код, вас за это не проклял. Nothing else matters.
    Беспокоиться об индусах, которым когда-нибудь случайно попадет в руки ваш код, вы все равно всерьез не будете.
    Ответ написан
    Комментировать
  • Как распределить кортеж названий фильмов по их расписаниям?

    Можно сделать так:
    from pprint import pprint
    films = ('Форсаж: Хоббс и Шоу', 'Вельзевул', 'Приключения Реми')
    rasp = (
        (('10:00', 'Kino Forum'), ('10:00', 'Kino Forum'), ('10:00', 'Lumiera Cinema (ЦУМ)')),
        (('12:50', 'Chaplin MEGA Park'), ('23:50', 'Chaplin MEGA Alma-Ata')),
        (('10:00', 'Lumiera Cinema (ЦУМ)'), ('10:00', 'Nomad Cinema'))
    )
    result = [
        (k, *v)
        for k, r in zip(films, rasp)
        for v in r
    ]
    
    pprint(result)


    result

    [('Форсаж: Хоббс и Шоу', '10:00', 'Kino Forum'),
     ('Форсаж: Хоббс и Шоу', '10:00', 'Kino Forum'),
     ('Форсаж: Хоббс и Шоу', '10:00', 'Lumiera Cinema (ЦУМ)'),
     ('Вельзевул', '12:50', 'Chaplin MEGA Park'),
     ('Вельзевул', '23:50', 'Chaplin MEGA Alma-Ata'),
     ('Приключения Реми', '10:00', 'Lumiera Cinema (ЦУМ)'),
     ('Приключения Реми', '10:00', 'Nomad Cinema')]

    Ответ написан
    3 комментария
  • Как сделать такую анимацию?

    sfi0zy
    @sfi0zy Куратор тега JavaScript
    Creative frontend developer
    Эта штука нынче затмила по популярности particles.js. Постоянно все о ней спрашивают, в том числе и на тостере:
    Можно ли использовать чужой js код?
    Как правильно вытащить код? с этой страницы...
    Ответ написан
    3 комментария
  • Программное решение для упорядочивания жизни?

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

    Основной свой вопрос я попробую решить для начала средствами личного репозитория на своем сервере, файлов в формате markdown и генератора статических сайтов.
    Ответ написан
    Комментировать
  • В чём польза Mixin'ов?

    Beshere
    @Beshere
    Разработчик
    Если нужно добавить в класс функциональности, но конструктивно желательно её отделить.

    Самый простой пример - экспорта объекта. Нехорошо будет, если процедуры экспорта вторгнутся в базовый класс: экспорт часто меняется, экспорт больше зависит от факторов, которые лежат в стороне, от факторов, которые влияют на базовый класс, возможно надо будет экспортировать несколькими способами.

    Поэтому делают примесь, где этот экспорт реализуют.
    Ответ написан
    Комментировать
  • Чем создание JVM под конкретные платформы "лучше", "проще", "продвинутее", "правильнее" написания компиляторов под те же платформы?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Упрощения для разработчиков инструментальных средств - это тема очень непростая. Намного легче объяснить плюсы с позиции прикладного программиста и пользователей ПО. В 2003-м году я участвовал в разработке одной системы на Java EE. Написанный мной и другими разработчиками код был скомпилирован с помощью Java 1.4, упакован в war и развёрнут на сервере заказчика. Это был сервер с 32-битными процессорами Xeon Prestonia, работавший под управление FreeBSD. Позже это приложение в том же war-файле было перенесено на сервер Fujitsu PRIMEPOWER с процессорами абсолютно иной архитектуры - SPARC, и управляемый очень отличающейся операционной системой - Solaris. Сейчас оно крутится на IBM'овских блэйдах c процами POWER и под управлением AIX, на сколько мне известно. Не удивлюсь, если через некоторое время приложение перенесут на что-нибудь с ARM'ами и под Linux или HP-UX. Все эти миграции выполняются без перекомпиляции и без привлечения разработчиков. Если бы приложение было написано на чём-нибудь вроде C++, код приложения пришлось бы портировать на каждую платформу и перекомпилировать. Это было долго, сложно и очень дорого.
    Ответ написан
    2 комментария
  • В чем правильно хранить словарь для Python?

    tsarevfs
    @tsarevfs
    C++ developer
    Для конфигов или статических данных удобно использовать json/yaml/xml файлы.
    Базу данных логично использовать там где данные структурированы и эту структуру важно поддерживать. Например оценки студентов доолжны принадлежать существующим студентам по существующим предметам. Также базы данных позволяют совершать транзакции, гарантируя что читать данные мы будем в правильном состоянии.
    Хранить данные в коде в большинстве случаев не очень удобно.
    Ответ написан
    Комментировать
  • Поля класса в Python перезаписываются?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Python
    Седой и строгий
    Вы модифицируете поле класса, а не его экземпляра. Исправить можно убрав объявление поля на уровне класса
    class SimpleClass:
        def __init__(self, args):
            self.number = args
    Ответ написан
    7 комментариев
  • Найти ошибку в коде?

    aRegius
    @aRegius
    Python Enthusiast
    Подскажите,что не так в моей программе ?

    Проверьте на предмет переопределения переменной k вот в этом месте:
    for k, v in ribsDict.items()
    Ответ написан
    Комментировать
  • Почему это пишется так?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Python
    Седой и строгий
    Это из-за того, что у вас стоит git bash. В cmd команда очистки консоли - это cls. Ни команды, ни утилиты clear в Widnows по умолчанию нет.
    Ответ написан
    2 комментария
  • Что нужно знать чтобы стать хорошим веб-программистом?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Прежде всего, web-приложения - это разновидность сетевых приложений. Поэтому обязательно нужно понимать, как работают сети и знать протоколы. Особенно HTTP.

    HTML и CSS знать обязательно. Желательно знать JavaScript, а вот библиотеку jQuery знать не обязательно. Нужно знать как минимум один серверный язык программирования. Это может быть PHP, а может какой-либо другой. Естественно, так как web-программирование - это тоже программирование, надо знать основные структуры данных, алгоритмы, парадигмы и паттерны. Так как редкий сайт бывает без базы данных, надо понимать принципы работы и проектирования реляционных БД и знать SQL. Желательно уверенно пользоваться Linux, так как ваш сайт будет работать над одной из его разновидностей. Желательно уметь настраивать http-сервера и сервера-приложений, а также знать механизмы их взаимодействия.

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

    @Mysterion
    pythonlearn.ru/perezagruzka-operatorov-python/obra...
    class A():
        def __setattr__(self, name, value):
            print("new attribute " + name + " with value " + str(value))
    
    o = A()
    
    o.newArg1 = 1
    o.newArg2 = 1
    Ответ написан
    1 комментарий
  • Можно-ли скачать видео с YouTube используя DevTools?

    Есть такая «секретная» ссылка: www.youtube.com/get_video_info?video_id=XXXXXX
    Вместо XXXXXX подставьте хэш видео, который в ссылке на ролик, типа youtu.be/BWCiWZtrWXU после слеша.

    По этой (первой) ссылке вернутся URL-encoded данные. Распакуйте их и возьмите параметр url_encoded_fmt_stream_map. Его значение опять надо распаковать как URL-параметры. И из результата вытащить параметр url – это ссылка на единый скачивабельный видеофайл.

    Например, в консоли браузера:
    function getUrlParams(search) {
        let hashes = search.slice(search.indexOf('?') + 1).split('&')
        let params = {}
        hashes.map(hash => {
            let [key, val] = hash.split('=')
            params[key] = decodeURIComponent(val)
        })
    
        return params
    }
    var s = '------'; // здесь длиннющая строка из ответа /get_video_info
    var a = getUrlParams(s);
    var b = getUrlParams(a.url_encoded_fmt_stream_map);
    console.log(b.url); // эту ссылку открываем в браузере - это скачиваемый видеофайл


    Очень надеюсь, что вы покопаетесь в этих данных более подробно, разберётесь, как получать прямые ссылки на скачиваемые файлы во всех форматах и размерах, которые предлагает YouTube, и напишете короткий материал на Хабр по результатам, а также опубликуете gist с рабочим кодом для консоли браузера.
    Ответ написан
    3 комментария