TGINSIGHT CHAT
Python Заметки
@pythonotes
EducationИнтересные заметки и обучающие материалы по Python Контакт: @paulwinex ⚠️ Рекламу на канале не делаю!⚠️ Хештеги для поиска: #tricks #libs #pep #basic #regex #qt #django #2to3 #source #offtop
Неодамнешни објави
Страница 16 од 32 · 384 објави
Објавено 5 мар.
В Python есть удобный почтовый debug-сервер. Он поможет проверить работу почты вашего web-проекта на этапе разработки без необходимости настраивать внешние сервисы или взаимодействие с реальными серверами Google или Yandex. Этот сервер просто печатает все сообщения в консоль. Таким образом удобно дебажить одноразовые ссылки активации или просто факт отправки письма по расписанию. Запускается очень просто: python3 -m smtpd -n -c DebuggingServer localhost:1025 Теперь настройте ваш проект на использование этого сервера. Например вот так настраивается Django: # settings.py if DEBUG: EMAIL_HOST = 'localhost' EMAIL_PORT = 1025 EMAIL_HOST_USER = '' EMAIL_HOST_PASSWORD = '' EMAIL_USE_TLS = False DEFAULT_FROM_EMAIL = '[email protected]' #django#tricks
Објавено 3 мар.
Несмотря на то, что проекты линейки Qt For Python (все версии PySide и PyQt) считаются полноценными production-решениями, они всё еще недоделаны и постоянно развиваются. В частности, не все классы оригинального С++ фреймворка реализованы с Python-версиях. Некоторые классы действительно пропущены за ненадобностью. Например, вместо QVariant можно использовать любой Python-объект, вместо QString простые Python-строки и тд. Но есть классы до которых просто еще не добрались разработчики. На этой странице↗️ можно посмотреть полный список нереализованных классов. При этом в разных биндингах состав может отличаться. К примеру те же QString и QVariant всё ещё доступны в PyQt4. #qt
Hashtags
Објавено 1 мар.
Как получить класс из модуля зная только его dotted-path? Что за dotted-path? Это путь импорта через точки вроде такого: "package.module.clsName" Так как мы не можем закинуть строку в директиву import то повторим то, что она делает только "вручную" mod = __import__('package.module', fromlist=['clsName']) cls = getattr(mod, 'clsName') Похожий способ с importlib import importlib module = importlib.import_module('package.module') cls = getattr(module, 'clsName') В обоих случаях приходится дополнительно обрабатывать строку чтобы отрезать имя класса от имени модуля. Так как мы сначала импортим модуль а потом достаём из него нужный объект. Есть ли способ просто закинуть всю строку и получить результат? Если пишете проект на Django то в нём есть функция import_string(). Она используется для импорта объектов, указанных в settings.py в виде dotted-path. from django.utils.module_loading import import_string cls = import_string('package.module.clsName') Если же у вас "чистый" Python то на помощь придёт модуль pydoc. У него тоже есть аналогичный метод для импорта объектов по dotted-path. from pydoc import locate cls = locate('package.module.clsName') В Python3.9 добавили еще один способ ресолвинга имени в объект. Теперь это самый актуальный способ на данный момент! import pkgutil cls = pkgutil.resolve_name('package.module.clsName') ____________ Конечно же это не относится только к классам. Точно так же можно импортнуть любой объект, вложенный в модуль. #tricks
Hashtags
Објавено 24 фев.
20 Февраля 1991 года вышла первая beta-версия Python v0.9.0. С тех пор минуло 30 лет! 😮 Сегодня мы имеем один из самых популярных языков программирования в мире. Поздравляем Python c юбилеем!⭐️🎉🎁🐍👍 Узнать, как это было можно, поставив себе первый релиз с помощью conda #offtop
Hashtags
Објавено 19 фев.
Еще один пример с ресурсами. Читаем картинку из PYZ архива сразу в QImage и далее используем как иконку в GUI. Без сохранения в промежуточный файл! Запускать так: python3 pkg_img.pyz ▫️Из зависимостей только PySide2. ▫️Помним, что это просто ZIP. То есть исходники можно легко достать из архива. #source
Hashtags
Објавено 17 фев.
Ранее я показал как упаковать ваше Python-приложение в ZIPAPP. В дополнение к этой теме покажу ещё один способ как достать изображение из архива, не сохраняя его на диск и сразу перегнать в класс PIL.Image для дальнейших манипуляций. Что есть ресурс в данном контексте? Это любой объект который можно прочитать как файл. В Python 3.7появился новый стандартный способ работы с ресурсами внутри пакетов. Это модуль importlib.resources. Его следует использовать и для случаев с контейнерами (ZIP, EGG) и для обычных пакетов. Для начала импортнём нужные модули from importlib.resources import read_binary from PIL import Image import io Читаем файл ресурса из пакета data = read_binary("package_name", "image.jpg") Создаём класс Image img = Image.open(io.BytesIO(data)) Картинка загружена в память, можно с ней что-то делать img.thumbnail((200, 200)) И после изменений сохранить в файл img.save(path, 'JPG') или использовать еще как-то img.show() Модуль получил бекпорт для старых версий в виде стороннего пакета importlib_resources. До появления этого модуля использовался модуль pkg_resources, входящий в состав setuptools. Но он теперь неактуален. #libs
Hashtags
Објавено 15 фев.
Как получить список всех модулей, доступных для импорта? pip list Эта команда выдаст список инсталлированных модулей, но не всех что доступны. help('modules') или python -m pydoc modules Покажет все модули которые можете импортнуть, включая те, что доступны благодаря переменной PYTHONPATH. Уже лучше, но проблема лишь в том, что функция печатает всё в аутпут, а нам нужен список строк. Конечно же в Python есть способ сделать всё просто и логично😉 import pkgutil modules = [m.name for m in pkgutil.iter_modules()] Вернёт имена всех модулей, доступных для импорта, кроме builtin модулей. Просто добавим их отдельно: import sys modules.extend(sys.builtin_module_names) Теперь мы получили полный список всех доступных для импорта модулей и пакетов, включая те, что подгружены через PYTHONPATH или динамически добавлены через sys.path. #tricks
Hashtags
Објавено 12 фев.
Как правильно проверить атрибуты доступа файла? То есть доступна ли запись в файл или является ли он исполняемым? Для этого в Python есть функция os.access() Проверять так: os.access(path, flag) Функция вернёт bool в зависимости от наличия указанного флага. Всего есть 4 флага проверки: os.F_OK - наличие файла на диске os.R_OK - доступ на чтение os.W_OK - доступ на запись os.X_OK - доступ на исполнение Например, вместо try-except лучше делать так (пример из документации): if os.access("myfile", os.R_OK): with open("myfile") as fp: return fp.read() #basic#libs
Објавено 10 фев.
GUI для Pyinstaller Auto PY to EXE — GUI-обёртка для Pyinstaller! Создаём команду сборки с помощью диалога. Для профессионалов пользы не много, а начинающим будет интересно посмотреть какие есть основные опции у Pyinstaller и как они выглядят в команде. 🎬 Видео урок 📦 Репозиторий ❓FAQ по использованию PS. Пусть вас не смущает слово EXE в названии и Windows в уроке. Эта штука работает и на Linux и на MacOS. #libs
Hashtags
Објавено 8 фев.
Как быстро отрезать от пути несколько элементов с любой стороны? Например, есть длинный путь: path = '/home/user/projects/proj1/assets/assetname/geo/publish/v001/body.geo' Для удобного отображения логов (или еще какой-то абстрактной задачи) я хочу видеть только 3 последних элемента. ▫️Сейчас мы не будем усложнять задачу с выделением только нужных элементов с парсингом самой строки. Работаем только с индексами элементов. ▫️Учитываем, что путь может прийти с неизвестно куда направленными слешами. ▫️Хочу реализацию в одну строку Вот так можно это сделать с помощью модуля os.path >>> os.path.join( ... *os.path.normpath( ... path ... ).replace( ... '\\', '/' ... ).split('/')[-3:]) 'publish/v001/body.geo' Монструозно, но работает👹 Более красивый вариант это класс pathlib.Path. У него есть две функции, которые нам помогут 🔸 Свойство parts, которое возвращает список элементов пути. 🔸 Конструктор Path() может принимать несколько строк которые объединятся в один путь. То есть аналогично функции join. >>> Path('folder', 'file') PosixPath('folder/file') Поэтому мы можем сделать так: >>> Path(*Path(path).parts[-5:]) PosixPath('publish/v001/body.geo') Ну вот, более лаконично (питонично🙄) А еще можно вырезать середину, оставив начало и конец >>> p = Path(path) >>> Path(*p.parts[:3],'...', *p.parts[-2:]) PosixPath('/home/user/.../v001/body.geo') #tricks#libs
Објавено 5 фев.
Можно ли создать инстанс класса используя квадратные скобки вместо круглых? 🙄 Казалось бы, чего сложного, делаем метод __getitem__ как classmethod и готово class MyClass: def __init__(self, value): self.value = value @classmethod def __getitem__(cls, item): return cls(item) Но нет, такой финт не сработает. >>> inst = MyClass[5] TypeError: 'type' object is not subscriptable Тип данного класса не поддерживает такой интерфейс. Чтобы поддерживал, нужно изменять его метакласс. Ниже представлен простой пример добавления метода __getitem__ в тип класса. class PresetsType(type): presets = { 'red': '#ff0000', 'green': '#00ff00', 'blue': '#0000ff'} def __getitem__(self, item): instance = self(self.presets[item]) return instance Получилось что-то вроде пресетов, доступных при создании инстанса через квадратные скобки. Теперь используем новый тип как метакласс нашего класса. class Color(metaclass=PresetsType): def __init__(self, value): self.value = value def __repr__(self): return f'<Color "{self.value}">' Можно тестить! # создаём инстанс обычным способом >>> c1 = Color('#ffb905') >>> print(c1) <Color "#ffb905"> # теперь через квадратные скобки >>> c2 = Color['red'] >>> print(c2) <Color "#ff0000"> На сколько пример актуальный в реальной работе, решать вам. Но он точно неочевидный😜 Как еще можно это использовать? 🔸 как-либо модифицировать класс и возвращать тоже класс вместо готового инстанса 🔸 возвращать сразу список инстансов. Например, в случаях когда используется срез 🔸 возвращать разные версии классов по имени под разные ситуации, например унаследованные классы с доп. интерфейсом Начиная с версии 3.7 у появилась возможность сделать тоже самое без мета класса! В PEP 560 добавили magic-метод __class_getitem__(cls). Теперь наш класс будет выглядеть так: class Color: presets = { 'red': '#ff0000', 'green': '#00ff00', 'blue': '#0000ff'} def __init__(self, value): self.value = value def __repr__(self): return f'<Color "{self.value}">' def __class_getitem__(cls, item): return cls(cls.presets[item]) #tricks
Hashtags
Објавено 3 фев.
Что делать если нужно поставить какую-то Python-библиотеку а root-прав нет? То есть в систему библиотеку никак и ничего не поставить. Есть как минимум два способа это решить правильно! 🔸 Сделать виртуальное окружение и ставить там что угодно. Это позволит создать полностью независимое исполняемое окружение для ваших приложений. Все библиотеки будут храниться в домашней директории юзера а значит доступ на запись имеется. Создать очень просто: python3 -m venv ~/venvs/myenvname Теперь активируем окружение # Linux source ~/venvs/myenvname/bin/activate # Windows %userprofile%\venvs\myenvname\Scripts\activate.bat Можно ставить любые библиотеки и запускать приложение. Это стандартный метод работы с любым проектом. Если еще не используете его, то пора начинать. Даже при наличии root доступа! 🔸 Бывает, что нет возможности запустить приложение из своего виртуального окружения. Например, его запускает какой-то сервис от вашего юзера и вставить активацию окружения вы не можете. В этом случае можно установить библиотеки для Python не глобально в систему, а только для юзера. Выполните этот код в консоли: python3 -m site Вы получите что-то такое: sys.path = [ '/home/user', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/home/user/.local/lib/python3.7/site-packages', ... ] USER_BASE: '/home/user/.local' USER_SITE: '/home/user/.local/lib/python3.7/site-packages' ENABLE_USER_SITE: True Нас интересует параметр USER_SITE. Это путь к пользовательским библиотекам, которые доступны по умолчанию, если они есть. Именно сюда будут устанавливаться модули если добавить флаг --user при установке чего-либо через pip pip install --user requests Для этой команды не нужны root-права. После неё можно запускать системный интерпретатор без виртуальных окружений и установленная библиотека будет доступна для текущего юзера. Параметр USER_BASE показывает корневую директорию для хранения user-библиотек. Её можно изменить с помощью переменной окружения PYTHONUSERBASE export PYTHONUSERBASE=~/pylibs python3 -m site ... USER_BASE: '/home/user/pylibs' USER_SITE: '/home/user/pylibs/lib/python3.7/site-packages' Получается некоторое подобие виртуального окружения для бедных 😁 которое можно менять через эту переменную (не делайте так!Лучше venv!) 🔸 Дописывание пути в PYTHONPATH Этот способ не входит в список "двух правильных", но тоже рабочий. Здесь придётся сделать всё несколько сложней. Сначала ставим библиотеку в любое место указывая путь установки pip3 install -t ~/mylibs modulename Библиотека установится без привязки к какому-либо интерпретатору. То есть по умолчанию не будет видна. Теперь в нужный момент добавляем этот путь в sys.path или в PYTHONPATH. Не буду советовать так делать. Единственный раз когда этот способ мне пригодился и решил поставленную задачу, это при создании общей библиотеки для кластера компьютеров. Модули лежат в сети и подгружаются для всех из одного и того же места. То есть обновлять файлы требуется только один раз а не на всех хосты отдельно. Минусы такого подхода: ▫️Нужно всем хостам пробить нужный путь в .bashrc или ещё куда-то чтобы он сетапился на старте. ▫️Чем больше хостов тем больше нагрузка на сеть. Иногда такой способ не подходит именно по этой причине. Тогда Ansible вам в помощь. ▫️Не очень подходит если хосты с разными операционками. Некоторые библиотеки различаются для Linux и Windows (там, где есть бинарники) и приходится мудрить более сложные схемы. #tricks#basic