TGTGInsighttelegram intelligenceLIVE / telegram public index
Назад кон каналите
Python Заметки avatar

TGINSIGHT CHAT

Python Заметки

@pythonotes

Education

Интересные заметки и обучающие материалы по Python Контакт: @paulwinex ⚠️ Рекламу на канале не делаю!⚠️ Хештеги для поиска: #tricks #libs #pep #basic #regex #qt #django #2to3 #source #offtop

Претплатници2,220Тековни претплатници
Следени објави384Број на индексирани објави
Неодамнешен опфат17,150Збир на неодамнешни прегледи
Неодамнешни објави

Неодамнешни објави

Страница 18 од 32 · 384 објави

Објавено 4 јан.

Подразумеваемые неймспейсы или неявные пакеты. Этот функционал добавлен в Python 3.3 Что он означает? Ранее, до 3.3 пакетами считались лишь директории, в которых есть файл __init__.py. Этот файл одновременно являлся свидетельством того, что директория это Python-пакет, и служил "телом" этого пакета. То есть местом, где можно написать код, как это делается внутри модуля. Этот код исполняется в момент импорта пакета, так что его принято называть "код инициализации пакета". Начиная с версии 3.3 Любая директория считается пакетом и Python будет пытаться использовать любую директорию для импорта. Конечно, не любую в файловой системе, а только те что находятся в sys.path. Это значит, что теперь __init__.py нужно делать только если: 🔸 вам требуется создать код инициализации пакета 🔸 нужна совместимость со старыми версиями Python На мой взгляд это немного упрощает разработку, делает её чище, но с другой стороны убивает некоторую однозначность происходящего. Например, я создал репозиторий со своей библиотекой и рядом положил код примеров или тестов. repo_name/ my_library/ __init__.py main.py examples/ exam1.py exam2.py В этом репозитории пакетом является только my_library, остальные директории это не пакеты, это просто дополнительный код в файлах. Директория examples не добавлена в sys.path, в ней нет рабочих модулей. Но если она лежит рядом с my_library, то Python вполне сможет импортнуть из неё модули, так как посчитает что examples это валидный пакет. Конечно, пример несколько надуманный. Никто не будет добавлять корень репозитория в sys.path. Но, я думаю, суть ясна. Иногда директория это просто директория а не пакет! #basic#pep

1,660 views

Hashtags

Објавено 4 јан.

Помните пост про абсолютный импорт? Он мне пригодился на днях, когда я объяснял особенности импортов в Python3. В процессе объяснения собрался небольшой конспект с заметками. Давайте рассмотрим их в следующих постах.

1,410 views

Објавено 1 јан.

Всех с Новым 2021🎉 Желаю всем нам чтобы год 2021 был сильно лучше чем 2020❗️ Между тем, ровно год назад был создан этот канал. Так что у нас тут немножко день рождения))) 🎂 Кажется пора подумать о новом контенте для канала 😉 #offtop

1,440 views

Hashtags

Објавено 25 дек.

Как в простом скрипте выполнить отложенное действие или даже несколько? Например, нам требуется удалить файл через 10 секунд после его создания, но при этом основной поток не должен просто остановиться на 10 секунд с помощью time.sleep(). Допустим, у нас также нет никаких асинхронных очередей задач типа rq или celery. Самый простой способ это класс threading.Timer. Это удобный способ выполнить отложенное действие, которое не блокирует основной поток. А так же это пример как писать многопоточный код на базе класса threading.Thread. Всё что делает этот класс, это создаёт отдельный поток, в котором и будет запущена функция ожидания. from threading import Timer import os filename = '/home/user/data.txt' t = Timer(10, lambda: os.remove(filename)) t.start() Можно проверить выполнилось ли действие с помощью неблокирующго метода ивента is_set() if t.finished.is_set(): # do something или отменить выполнение t.cancel() А что будет если процесс интерпретатора завершится ДО завершения таймаута? Тут у нас два варианта: 🔸 Если поток запущен как Daemon то он завершится вместе с программой, тем самым отменив выполнение колбека. 🔸 В противном случае программа не завершится пока поток не завершится. По умолчанию режим Daemon отключен, то есть программа в любом случае дождётся исполнения колбека и только потом завершится. Переключение режима следует делать ДО запуска потока! t = Timer(...) t.setDaemon(True) t.start() #tricks

1,670 views

Hashtags

Објавено 23 дек.

Для тех кто пропустил релиз Qt6! PySide6 уже доступен! Для старта можно взять эти странички: https://wiki.qt.io/Qt_for_Python https://doc.qt.io/qtforpython/ https://doc.qt.io/qtforpython/tutorials/index.html Там же есть ссылка на репозиторий примеров https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples #qt

1,420 views

Hashtags

Објавено 14 дек.

Как разделить строку с shell-командой на отдельные аргументы в виде списка? Если сделать просто сплит по пробелу то получим то что надо, кроме случаев со вставками текста с пробелами. Например так: >>> '-arg "I Am Groot"'.split(' ') ['-arg', '"I', 'Am', 'Groot"'] Чтобы учитывать текст в кавычках как единый аргумент можно воспользоваться функцией shlex.split() Кто читает мой канал давно, уже в курсе. А что делать, если нужно обратное действие? Объединить аргументы из списка в строку и при этом добавить кавычки в аргумент с пробелами. Конечно, если вы используете subprocess то он сам всё разрулит. Но если вам нужна именно команда одной строкой, то можно воспользоваться готовой функцией в том же subprocess. >>> from subprocess import list2cmdline >>> list2cmdline(['-arg', 'I Am Groot']) '-arg "I Am Groot"' Он также позаботится об экранировании уже имеющихся кавычек >>> list2cmdline(['-arg', 'I Am "Groot"']) '-arg "I Am \"Groot\""' А вот так он может "схлопнуть" в команду JSON >>> list2cmdline(['--json', json.dumps({'key': 'value'})]) '--json "{\"key\": \"value\"}"' _______________ Возможно кто-то спросит, а зачем соединять аргументы в строку если subprocess сам это сделает а os.system не наш путь? Мне как-то потребовалось отправлять команду на удалённое выполнение и в API поддерживалось указание команды только строкой. Так что всякое бывает) #libs#basic

1,670 views

Hashtags

Објавено 11 дек.

Еще раз про JSON Для создания кастомной сериализации объектов в JSON не обязательно создавать класс-сериализатор. Достаточно указать функцию default() которую в свою очередь подать в виде лямбды. За читаемость примера не ручаюсь но выйдет что-то вроде такого: json.dumps(my_data, default=lambda obj: { 'type': f'{obj.__class__.__module__}.{obj.__class__.__name__}', 'data': getattr(obj, '__dict__', repr(obj))}) В примере я добавил полный путь к классу включая имя модуля. ⚠️ Повторяю! В ситуации, когда данные неизвестны, такой подход может привести к непредсказуемому поведению! Лично я использовал его только для дебага, когда требовалось получить хоть что-то в виде JOSN а не ошибку. Явное лучше чем неявное 😉 Кстати, обычная функция часто лучше чем лямбда 😬 Так что вам эта же функция в нормальном виде def default_hook(obj): return { 'type': f'{obj.__class__.__module__}.' f'{obj.__class__.__name__}', 'data': getattr(obj, '__dict__', repr(obj)) } json.dumps(my_data, default=default_hook) Почему бы не организовать поддержку всех стандартных объектов Python в стандартном JSON-энкодере? Я думаю дело в неочевидности этого процесса. Как можно сериализовать float? Тут вполне очевидно. А как сериализовать datetime? Вот тут тысяча и один вариант как можно форматировать дату. Поэтому данный этап отадётся на откуп разработчику. Меня устроило бы добавление в спецификацию класса метода __json__ по аналогии с __fspath__, который использовался бы стандартным энкодером. Метод возвращал бы поддерживаемый для JSON объект. Тогда не требуется что-то указывать в функции dump() и наш класс может использоваться в других модулях, где код уже записан и вставить что-то в default м не можем. Но пока этого нет (и будет ли?) мы по-прежнему добавляем в класс метод toJson() и вызываем его, отправляя в json.dump(). #tricks#libs

1,390 views

Hashtags

Објавено 9 дек.

В прошлом посте мы научили JSON понимать новый тип данных. Но что если придётся записывать в JSON много разных неподдерживаемых типов? Описывать для каждого отдельный if isinstance()? А если нам не известно что именно придётся сериализовать и нужно поддерживать в принципе всё что угодно? Ну хотя бы как-то записать объект чтобы не было ошибки и чтобы объект записался в JSON более менее информативно. В этом случае можно вызвать стандартные способы репрезентации объекта. Самое простое это функция repr(). И тут уж как повезёт с тем, как именно разработчик позаботился о таком поведении его класса. Более описательный метод, это закинуть объект в словарь с именем класса и данными инстанса. В общем, возвращаясь к примеру из прошлого поста, мы просто убираем проверку конкретного типа class MySerializer(json.JSONEncoder): def default(self, obj): return {'type': obj.__class__.__name__, 'data': vars(obj)} Функция vars() аналогична обращению к атрибуту __dict__ Теперь любой ранее неизвестный объект будет успешно сериализован... или нет? >>> json.dumps(datetime.datetime.now(), cls=MySerializer) AttributeError: 'datetime.datetime' object has no attribute '__dict__ Так уж вышло, что не любой объект имеет атрибут __dict__. В таком случае используем repr() class MySerializer(json.JSONEncoder): def default(self, obj): return {'type': obj.__class__.__name__, 'data': getattr(obj, '__dict__', repr(obj))} То есть мы пробуем забрать данные инстанса, и если не получается то вызываем стандартное строковое представление объекта в надежде что разработчики позаботились о нём. >>> json.dumps(datetime.now(), cls=MySerializer) '{"type": "datetime", "data": "datetime.datetime(...)"}' ⚠️ PS: Не могу сказать что решение идеально. Такую неявную сериализацию можно сравнить с замалчиванием ошибок. try: do_something() except: pass То есть в какой-то момент вы будете получать совершенно бесполезные данные и придётся искать где это происходит. Если не определён метод __repr__ то вы получите что-то вроде такого <__main__.MyClass object at 0x00000147CE48CBC8> Что с этим делать? Непонятно! 🤔 Скорее всего найдутся люди, которые осудят такой подход. Может выбрасывать ошибку в случае отсутствия метода __repr__ в классе? #libs#tricks

1,230 views

Hashtags

Објавено 7 дек.

JSON — весьма удобный формат для передачи или хранения данных. Но у него есть одна особенность: по умолчанию он умеет сериализовать только стандартные типы данных Python, такие как int, float, list, dict и тд. Как только появляется какой-либо класс мы терпим фиаско с ошибкой что-то вроде TypeError: Object of type MyClass is not JSON serializable Причём не поддерживаются даже стандартные классы типа datetime или re.Pattern😢. Повезло лишь некоторым классам, которые предназначены для хранения данных, например namedtuple или defaultdict. Как сделать так, чтобы любой объект смог сериализоваться в JSON? Обычный подход это создать свой класс-сериализатор, где и будет прописан алгоритм превращения объектов в строку, словарь или что-то обычное для JSON Допустим, у меня есть мой класс: class MyClass: def __init__(self): self.x = 100 Создадим сериализатор который умеет понимать такой тип объекта. Его задача: сохранить имя типа и данные инстанса чтобы потом можно было восстановить объект обратно. Для этого переопределим метод default(), котоырй по умолчанию выбрасывает ошибку когда объект не поддерживается. class MySerializer(json.JSONEncoder): def default(self, obj): if isinstance(obj, MyClass): return {'type': MyClass.__name__, 'data': obj.__dict__} return super().default(obj) Пробуем закодировать объект в JSON используя мой сериализатор >>> mc = MyClass() >>> json.dumps(mc, cls=MySerializer) '{"type": "MyClass", "data": {"x": 100}}' Отлично, теперь json понимает мой тип! 😎 #libs

1,270 views

Hashtags

Објавено 3 дек.

3Dшников и всех кто в теме, повсеместно поздравляю! 🥳 #offtop

1,380 views

Hashtags

Објавено 2 дек.

­ В стандартных библиотеках Python есть средства для текстового процессинга. Например difflib, fnmatch или тотже re. Но в реальной работе они оказываются "многословны" при при поиске нечётких совпадений строк. Например, если вы пишете голосовой помощник и вам требуется определить произнесённые ключевые слова. Или в вашем телеграм-боте пользователь вводит определённые слова и возможны ошибки или сокращения. Вместо того чтобы писать большой список вариантов каждого слова следует применять нечёткое совпадение в тексте. Для этого хорошо подойдёт библиотека fuzzywuzzy. Она может посчитать на сколько один текст похож на другой или найти из списка строк самое похожее на заданный текст. Пример поиска имени месяца по введённому юзером тексту. Список месяцев берём из примера прошлого поста. >>> from fuzzywuzzy import process >>> import calendar >>> months = list(calendar.month_name)[1:] # достаём все совпадения. Функция возвращает само слово и степень похожести >>> process.extract('январ', months, limit=3) [('Январь', 91), ('Март', 44), ('Сентябрь', 40)] # можно сразу взять самое похожее совпадение >>> process.extractOne('фев', months) ('Февраль', 90) Конечно, на этом возможности не ограничены. Можно искать в текстах плагиат, анализировать текст на статистику похожих слов, создать автокомплиты с исправлениями в текстовых редакторах и тд. #libs

1,340 views

Hashtags

Објавено 30 ное.

Как получить список месяцев или дней недели на русском языке? Можно "нахардкодить" список прямо в своём коде😖. Но лучше воспользоваться стандартным модулем calendar установив нужную локализацию. >>> import calendar >>> import locale >>> locale.setlocale(category =locale.LC_ALL, locale="Russian") >>> print(list(calendar.month_name)[1:]) ['Январь', 'Февраль', 'Март', ... >>> print(list(calendar.day_name)) ['понедельник', 'вторник', 'среда', ... >>> print(list(calendar.day_abbr)) ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'] Модуль datetime тоже будет с переводом >>> import datetime >>> datetime.date.today().strftime('%B %Y года, %A') 'Ноябрь 2020 года, суббота' (кстати, именно так получается список month_name) А вот так можно распечатать календарь на год на русском прямо в терминал: print(calendar.LocaleTextCalendar(locale="Russian_Russia").formatyear(2021)) #libs#tricks

1,270 views

Hashtags

12•••10•••1617181920•••303132
ПретходнаСтраница 18 од 32Следна