GUI для Pyinstaller
Auto PY to EXE — GUI-обёртка для Pyinstaller!
Создаём команду сборки с помощью диалога. Для профессионалов пользы не много, а начинающим будет интересно посмотреть какие есть основные опции у Pyinstaller и как они выглядят в команде.
🎬 Видео урок
📦 Репозиторий
❓FAQ по использованию
PS. Пусть вас не смущает слово EXE в названии и Windows в уроке. Эта штука работает и на Linux и на MacOS.
#libs
Auto PY to EXE — GUI-обёртка для Pyinstaller!
Создаём команду сборки с помощью диалога. Для профессионалов пользы не много, а начинающим будет интересно посмотреть какие есть основные опции у Pyinstaller и как они выглядят в команде.
🎬 Видео урок
📦 Репозиторий
❓FAQ по использованию
PS. Пусть вас не смущает слово EXE в названии и Windows в уроке. Эта штука работает и на Linux и на MacOS.
#libs
Как правильно проверить атрибуты доступа файла? То есть доступна ли запись в файл или является ли он исполняемым?
Для этого в Python есть функция os.access()
Проверять так:
Всего есть 4 флага проверки:
Например, вместо try-except лучше делать так (пример из документации):
Для этого в 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Как получить список всех модулей, доступных для импорта?
Уже лучше, но проблема лишь в том, что функция печатает всё в аутпут, а нам нужен список строк.
Конечно же в Python есть способ сделать всё просто и логично😉
Просто добавим их отдельно:
#tricks
pip listЭта команда выдаст список инсталлированных модулей, но не всех что доступны.
help('modules')
илиpython -m pydoc modulesПокажет все модули которые можете импортнуть, включая те, что доступны благодаря переменной PYTHONPATH.
Уже лучше, но проблема лишь в том, что функция печатает всё в аутпут, а нам нужен список строк.
Конечно же в Python есть способ сделать всё просто и логично😉
import pkgutilВернёт имена всех модулей, доступных для импорта, кроме builtin модулей.
modules = [m.name for m in pkgutil.iter_modules()]
Просто добавим их отдельно:
import sysТеперь мы получили полный список всех доступных для импорта модулей и пакетов, включая те, что подгружены через PYTHONPATH или динамически добавлены через sys.path.
modules.extend(sys.builtin_module_names)
#tricks
Ранее я показал как упаковать ваше Python-приложение в ZIPAPP.
В дополнение к этой теме покажу ещё один способ как достать изображение из архива, не сохраняя его на диск и сразу перегнать в класс PIL.Image для дальнейших манипуляций.
Что есть ресурс в данном контексте? Это любой объект который можно прочитать как файл.
В Python 3.7 появился новый стандартный способ работы с ресурсами внутри пакетов. Это модуль importlib.resources.
Его следует использовать и для случаев с контейнерами (ZIP, EGG) и для обычных пакетов.
Для начала импортнём нужные модули
До появления этого модуля использовался модуль pkg_resources, входящий в состав setuptools. Но он теперь неактуален.
#libs
В дополнение к этой теме покажу ещё один способ как достать изображение из архива, не сохраняя его на диск и сразу перегнать в класс 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")
Создаём класс Imageimg = Image.open(io.BytesIO(data))Картинка загружена в память, можно с ней что-то делать
img.thumbnail((200, 200))И после изменений сохранить в файл
img.save(path, 'JPG')или использовать еще как-то
img.show()Модуль получил бекпорт для старых версий в виде стороннего пакета importlib_resources.
До появления этого модуля использовался модуль pkg_resources, входящий в состав setuptools. Но он теперь неактуален.
#libs
Telegram
Python Заметки
Вы уже знаете, что можно добавить ZIP архив в PYTHONPATH и использовать его как библиотеку.
У Python есть еще одна интересная стандартная библиотека zipapp. Она поможет создать стендалон (или почти стендалон) приложение с помощью ZIP архива.
На самом деле…
У Python есть еще одна интересная стандартная библиотека zipapp. Она поможет создать стендалон (или почти стендалон) приложение с помощью ZIP архива.
На самом деле…
pkg_img.pyz
8.7 KB
Еще один пример с ресурсами.
Читаем картинку из PYZ архива сразу в QImage и далее используем как иконку в GUI.
Без сохранения в промежуточный файл!
Запускать так:
▫️Помним, что это просто ZIP. То есть исходники можно легко достать из архива.
#source
Читаем картинку из PYZ архива сразу в QImage и далее используем как иконку в GUI.
Без сохранения в промежуточный файл!
Запускать так:
python3 pkg_img.pyz▫️Из зависимостей только PySide2.
▫️Помним, что это просто ZIP. То есть исходники можно легко достать из архива.
#source
20 Февраля 1991 года вышла первая beta-версия Python v0.9.0.
С тех пор минуло 30 лет! 😮
Сегодня мы имеем один из самых популярных языков программирования в мире.
Поздравляем Python c юбилеем! ⭐️🎉🎁🐍👍
Узнать, как это было можно, поставив себе первый релиз с помощью conda
#offtop
С тех пор минуло 30 лет! 😮
Сегодня мы имеем один из самых популярных языков программирования в мире.
Поздравляем Python c юбилеем! ⭐️🎉🎁🐍👍
Узнать, как это было можно, поставив себе первый релиз с помощью conda
#offtop
Python.org
Ancient Releases
The official home of the Python Programming Language
Как получить класс из модуля зная только его dotted-path?
Что за dotted-path? Это путь импорта через точки вроде такого:
Есть ли способ просто закинуть всю строку и получить результат?
Если пишете проект на Django то в нём есть функция import_string(). Она используется для импорта объектов, указанных в settings.py в виде dotted-path.
Конечно же это не относится только к классам. Точно так же можно импортнуть любой объект, вложенный в модуль.
#tricks
Что за dotted-path? Это путь импорта через точки вроде такого:
"package.module.clsName"Так как мы не можем закинуть строку в директиву import то повторим то, что она делает только "вручную"
mod = __import__('package.module', fromlist=['clsName'])
cls = getattr(mod, 'clsName')
Похожий способ с importlibimport 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Если же у вас "чистый" Python то на помощь придёт модуль pydoc. У него тоже есть аналогичный метод для импорта объектов по dotted-path.
cls = import_string('package.module.clsName')
from pydoc import locateВ Python3.9 добавили еще один способ ресолвинга имени в объект. Теперь это самый актуальный способ на данный момент!
cls = locate('package.module.clsName')
import pkgutil____________
cls = pkgutil.resolve_name('package.module.clsName')
Конечно же это не относится только к классам. Точно так же можно импортнуть любой объект, вложенный в модуль.
#tricks
Несмотря на то, что проекты линейки Qt For Python (все версии PySide и PyQt) считаются полноценными production-решениями, они всё еще недоделаны и постоянно развиваются. В частности, не все классы оригинального С++ фреймворка реализованы с Python-версиях.
Некоторые классы действительно пропущены за ненадобностью. Например, вместо QVariant можно использовать любой Python-объект, вместо QString простые Python-строки и тд.
Но есть классы до которых просто еще не добрались разработчики.
На этой странице↗️ можно посмотреть полный список нереализованных классов. При этом в разных биндингах состав может отличаться. К примеру те же QString и QVariant всё ещё доступны в PyQt4.
#qt
Некоторые классы действительно пропущены за ненадобностью. Например, вместо QVariant можно использовать любой Python-объект, вместо QString простые Python-строки и тд.
Но есть классы до которых просто еще не добрались разработчики.
На этой странице↗️ можно посмотреть полный список нереализованных классов. При этом в разных биндингах состав может отличаться. К примеру те же QString и QVariant всё ещё доступны в PyQt4.
#qt
В Python есть удобный почтовый debug-сервер. Он поможет проверить работу почты вашего web-проекта на этапе разработки без необходимости настраивать внешние сервисы или взаимодействие с реальными серверами Google или Yandex. Этот сервер просто печатает все сообщения в консоль.
Таким образом удобно дебажить одноразовые ссылки активации или просто факт отправки письма по расписанию.
Запускается очень просто:
Таким образом удобно дебажить одноразовые ссылки активации или просто факт отправки письма по расписанию.
Запускается очень просто:
python3 -m smtpd -n -c DebuggingServer localhost:1025Теперь настройте ваш проект на использование этого сервера. Например вот так настраивается Django:
# settings.py#django #tricks
if DEBUG:
EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False
DEFAULT_FROM_EMAIL = '[email protected]'
8 Марта🌸 вышел альфа-релиз Python 3.10.0a6
Уже сейчас можно его скачать и попробовать новый синтаксис Switch Statement, о котором я упоминал ранее.
В Python его назвали Structural pattern matching
Итак, как это теперь выглядит?
#tricks
Уже сейчас можно его скачать и попробовать новый синтаксис Switch Statement, о котором я упоминал ранее.
В Python его назвали Structural pattern matching
Итак, как это теперь выглядит?
match QUERY:Для объединения нескольких значений в одном кейсе используем вертикальную черту
case VALUE1:
return 1
case VALUE2:
return 2
case VALUE3:
return 3
case _: # default
return 0
match QUERY:Также можно добавлять дополнительные проверки с if
case VALUE1 | VALUE2:
return 3
case _: # default
return 0
match QUERY:Выглядит как синтаксический сахар для конструкции
case VALUE1:
return 1
case VALUE2 | VALUE3 if x < 5:
return 2
case _: # default
return 0
if..elif..else. В целом не плохо, но и непривычно)#tricks
Python.org
Python Release Python 3.10.0a6
The official home of the Python Programming Language
Для Python3.8 в PEP0578 добавили функционал аудита Runtime операций. Это позволяет выполнять хуки (функции) при возникновении определённых событий в интерпретаторе.
Этот функционал разработан, прежде всего, для специалистов по безопасности. Аудит позволяет перехватывать различные действия и проверять их допустимость.
Полный список стандартных аудит-ивентов можно посмотреть здесь. Из названий становится ясно что мы можем перехватить. Например, мы можем перехватить факт открытия файла (
Примеры использования:
▫️Представим, что после разработки и долгих тестирований веб сервиса вы могли где-то оставить функцию ручного ввода данных в консоль. На продакшене такое недопустимо. С помощью аудита можно вызвать исключение перехватив ивент
▫️Ивент
Как добавить свой хук?
Для первого теста выполните такой код в самом начале работы приложения
Теперь давайте посмотрим какие web-коннекты создаются при работе нашего кода. Для запросов используем requests.
А так же:
▫️есть платформозависимые хуки (например взаимодействие с winapi)
▫️можно писать хуки на Си
▫️так как это мера для обеспечения безопасности, нет способа удалить хуки после добавления.
Напоминаю, доступно в Python3.8+
#pep #tricks
Этот функционал разработан, прежде всего, для специалистов по безопасности. Аудит позволяет перехватывать различные действия и проверять их допустимость.
Полный список стандартных аудит-ивентов можно посмотреть здесь. Из названий становится ясно что мы можем перехватить. Например, мы можем перехватить факт открытия файла (
open), импорта модуля (import), копирование файла (shutil.copyfile), запуск процесса (subprocess.Popen) и тд. Как минимум мы можем залогировать данное событие, как максимум, вызвать аварийное завершение программы.Примеры использования:
▫️Представим, что после разработки и долгих тестирований веб сервиса вы могли где-то оставить функцию ручного ввода данных в консоль. На продакшене такое недопустимо. С помощью аудита можно вызвать исключение перехватив ивент
builtins.input
▫️С помощью ивента socket.getaddrinfo можно определить на какие сайты юзер заходил с помощью вашего приложения.▫️Ивент
exec позволит проверить загруженный объект кода перед его исполнением. Например выявить потенциально опасный код, или оставленные API ключи в строковых переменных.Как добавить свой хук?
Для первого теста выполните такой код в самом начале работы приложения
import sysКаждый хук вызывается для всех событий, поэтому мы можем с помощью одного хука увидеть всё что происходит в интерпретаторе.
def hook(event, args):
print(f'EVENT: {event}{args}')
sys.addaudithook(hook)
Теперь давайте посмотрим какие web-коннекты создаются при работе нашего кода. Для запросов используем requests.
import sysВ аутпуте вы увидите домен, на который был сделан запрос.
import requests
def socket_hook(event, args):
if event == 'socket.getaddrinfo':
print(args[0])
sys.addaudithook(socket_hook)
requests.get('https://google.com')
А так же:
▫️есть платформозависимые хуки (например взаимодействие с winapi)
▫️можно писать хуки на Си
▫️так как это мера для обеспечения безопасности, нет способа удалить хуки после добавления.
Напоминаю, доступно в Python3.8+
#pep #tricks
Python.org
PEP 578 -- Python Runtime Audit Hooks
The official home of the Python Programming Language
Кроме стандартных системных ивентов аудита можно вызывать свои ивенты. Для этого используется функция sys.audit()
Такое будет полезно если вы разрабатываете серьезную библиотеку в которой вопрос безопасности стоит не на последнем месте. Дать возможность другим разработчикам добавлять свои проверки будет хорошей практикой!
Хотя никто не запрещает придумать свой способ использования перехвата подобных событий.
Особенно это будет знакомо тем, кто пишет приложения на PyQt. Очень уж похоже на систему сигнал/слот в режиме DirectConnection.
▫️ следует вызывать sys.audit() ПОСЛЕ проверки данных но ДО фактического применения и исполнения логики. Это поможет избежать лишней проверки данных вне основной логики и прервать операцию в нужный момент.
▫️ в имени ивента рекомендуется использовать неймспейс с именем вашего модуля.
#tricks
import sysПросто указываем имя ивента первым аргументом и далее любые аргументы.
def my_hook(event, args):
if event == 'mymodule.myevent':
print('Catched!', args)
sys.addaudithook(my_hook)
sys.audit('mymodule.myevent', 1, 2, 3)
Такое будет полезно если вы разрабатываете серьезную библиотеку в которой вопрос безопасности стоит не на последнем месте. Дать возможность другим разработчикам добавлять свои проверки будет хорошей практикой!
Хотя никто не запрещает придумать свой способ использования перехвата подобных событий.
Особенно это будет знакомо тем, кто пишет приложения на PyQt. Очень уж похоже на систему сигнал/слот в режиме DirectConnection.
▫️ следует вызывать sys.audit() ПОСЛЕ проверки данных но ДО фактического применения и исполнения логики. Это поможет избежать лишней проверки данных вне основной логики и прервать операцию в нужный момент.
▫️ в имени ивента рекомендуется использовать неймспейс с именем вашего модуля.
#tricks
Стандартная Django админка работает стабильно но не могу сказать что она меня устраивает. Да, есть базовый набор стандартного функционала, но чего-то всегда не хватает. Может автокомплитов а может тёмной темы. 😎
Долгое время я использовал DjangoSuit, но проект заглох на невыпущенной альфе 2й версии которая в Django3 и вовсе не поддерживается.
Что же можно сегодня посоветовать?
На сегодняшний день у меня два фаворита:
🚀 DjangoJET
🌎 сайт
🗄 репозиторий
▶️ видео
Крутая и красивая админка с кучей плюшек.
▫️автокомплиты с AJAX подгрузкой
▫️темы
▫️дашборды
▫️респонсив
▫️кастомизация панелей прямо в админке
Стоит денег для коммерческих продуктов. Для опенсорса бесплатно (AGPL)!
🎷 Django Jazzmin
🗄репозиторий
Не такая пафосная но от этого не менее крутая админка.
▫️полностью кастомизируется
▫️много готовых тем и возможность собрать свою прямо в админке
▫️Bootsrtap Model окна вместо всплывающих окон
▫️интегрирован Select2
▫️респонсив
Знаете еще крутые админки? Напишите в комментах!
#django #libs
Долгое время я использовал DjangoSuit, но проект заглох на невыпущенной альфе 2й версии которая в Django3 и вовсе не поддерживается.
Что же можно сегодня посоветовать?
На сегодняшний день у меня два фаворита:
🚀 DjangoJET
🌎 сайт
🗄 репозиторий
▶️ видео
Крутая и красивая админка с кучей плюшек.
▫️автокомплиты с AJAX подгрузкой
▫️темы
▫️дашборды
▫️респонсив
▫️кастомизация панелей прямо в админке
Стоит денег для коммерческих продуктов. Для опенсорса бесплатно (AGPL)!
🎷 Django Jazzmin
🗄репозиторий
Не такая пафосная но от этого не менее крутая админка.
▫️полностью кастомизируется
▫️много готовых тем и возможность собрать свою прямо в админке
▫️Bootsrtap Model окна вместо всплывающих окон
▫️интегрирован Select2
▫️респонсив
Знаете еще крутые админки? Напишите в комментах!
#django #libs
Иногда хочется чтобы в качестве объекта передачи данных был удобный класс но не хочется (или нет возможности) писать сераиализатор в JSON для него. Идеально было бы сделать класс, который сам умел бы сериализоваться в JSON дефолтным модулем без указания дополнительных сериализаторов.
Как это сделать?
Стандартный модуль JSON умеет правильно сериализовать стандартные типы. Но нам нужен кастомный класс с удобными методами и свойствами. Ответ очевиден - наследуемся от стандартного типа!
В качестве базового типа возьмем словарь. Например, мне нужен класс некоего абстрактного элемента списка с именем и индексом. Тогда реализация может быть такой.
Для более сложных случаев можно посмотреть на библиотеку dataclasses-json, которая поможет сериализовать dataclasses.
#tricks #libs
Как это сделать?
Стандартный модуль JSON умеет правильно сериализовать стандартные типы. Но нам нужен кастомный класс с удобными методами и свойствами. Ответ очевиден - наследуемся от стандартного типа!
В качестве базового типа возьмем словарь. Например, мне нужен класс некоего абстрактного элемента списка с именем и индексом. Тогда реализация может быть такой.
class Item(dict):Я добавил два свойства с простым переназначением данных в словарь. Но предполагается, что там будут проверки значений и иные вычисления. Еще хорошо бы добавить методы
def __init__(self, name, index=0):
super().__init__(name=name, index=index)
@property
def name(self):
return self['name']
@name.setter
def name(self, value):
self['name'] = value
@property
def index(self):
return self['index']
@index.setter
def index(self, value):
self['index'] = value
def __setitem__(self, key, value):
if key not in ['index', 'name']:
raise KeyError
super().__setitem__(key, value)
__str__ и __repr__.>>> it = Item('item name')
>>> it.name
'item name'
>>> it.index
0
Также можно добавить любые методы классу. Например я переопределил __setitem__ чтобы нельзя было задать иные ключи.>>> it['key'] = 123Хотя, можно сделать как-то иначе. К примеру, все отличные от основных ключи записывать в отдельный ключ.
KeyError
def __setitem__(self, key, value):Ну а главная особенность этого класса в том, что он легко понимается стандартным модулем json (конечно, если значения ключей это тоже стандартные типы или наследованные от них)
if key not in ['index', 'name']:
self['meta'][key] = value
else:
super(Item, self).setitem(key, value)
>>> json.dumps(item)Самый очевидный пример, использование в библиотеке requests. Передавая объект в аргумент json, мы не можем повлиять на его сериализацию, то есть добавить класс-сериализатор. Там ожидается готовый словарь или иной совместимый тип.
'{"index": 2, "name": "item name"}'
import requestsА вот так выглядит альтернатива с методом toJson()
requests.post(url, json=item)
requests.post(url, data=item.toJson(),А ещё ничто не мешает нам в любой момент конвертнуть наш класс в обычный словарь
headers={'Content-Type': 'application/json'})
>>> dict(item)Не спорю, возможно есть более "умные" решения этой задачи 🤓 Но, тем не менее, аналогичным образом работает стандартный collections.namedtuple. Он тоже наследуется от стандартного tuple, расширяет его функционал и сериализуется без дополнительных средств.
{"index": 2, "name": "item name"}
Для более сложных случаев можно посмотреть на библиотеку dataclasses-json, которая поможет сериализовать dataclasses.
#tricks #libs
Порой админу проще написать огромный bash-скрипт с запросами в БД и парсингом через регулярки чем пытаться тоже самое изобразить в Python. Тоже самое верно и в обратном случае. Даже простые shell команды порой удобней записать в Python скрипт чем на bash. Правда, в обоих случаях выглядит это всё не очень.
Если сталкивались с таким, то поймёте о чем я😢
Специально для вас сделал подборку библиотеки для работы с shell из Python. Чтобы ваш код оставался красивым и читабельным!
➡️ sh
Переносим bash синтаксис в Python. Удобно и немногословно.
Ранее я уже рассказывал про этот модуль, можно глянуть в этом посте.
➡️ plumbum
Аналогичен sh но со своими плюшками. Например встроенная колоризация вывода
➡️ pexpect
Библиотека для интерактивного взаимодействия с процессом через stdin/stdout.
Нашел небольшой гайд на русском.
➡️ shell_command
Еще одна библиотека для вызова shell-команд. Ориентируется на безопасность вызываемого кода и заточена на удобство для админов.
Бонусом
➡️ envoy
Обёртка вокруг subprocess делающая его использование еще проще и минималистичней.
_______________
Кстати, до Python 2.6 вместо subprocess была библиотека commands. Выглядит достаточно аскетично)
#libs
Если сталкивались с таким, то поймёте о чем я😢
Специально для вас сделал подборку библиотеки для работы с shell из Python. Чтобы ваш код оставался красивым и читабельным!
➡️ sh
Переносим bash синтаксис в Python. Удобно и немногословно.
Ранее я уже рассказывал про этот модуль, можно глянуть в этом посте.
➡️ plumbum
Аналогичен sh но со своими плюшками. Например встроенная колоризация вывода
➡️ pexpect
Библиотека для интерактивного взаимодействия с процессом через stdin/stdout.
Нашел небольшой гайд на русском.
➡️ shell_command
Еще одна библиотека для вызова shell-команд. Ориентируется на безопасность вызываемого кода и заточена на удобство для админов.
Бонусом
➡️ envoy
Обёртка вокруг subprocess делающая его использование еще проще и минималистичней.
_______________
Кстати, до Python 2.6 вместо subprocess была библиотека commands. Выглядит достаточно аскетично)
#libs
Telegram
Python Заметки
Python + bash
Если вам часто требуется запускать shell команды из Python-кода, какой способ вы используете?
Самый низкоуровневый это функция os.system(), либо os.popen(). Рекомендованный способ это subprocess.call(). Но это всё еще достаточно неудобно.
Советую…
Если вам часто требуется запускать shell команды из Python-кода, какой способ вы используете?
Самый низкоуровневый это функция os.system(), либо os.popen(). Рекомендованный способ это subprocess.call(). Но это всё еще достаточно неудобно.
Советую…
https://devdocs.io/python~3.9/
Интерактивный поиск по документации Python. Просто наберите имя функции, класса или модуля и сразу получите статью.
Поиск умный, может найти неточное совпадение. Например когда допустили опчепятку в слове. Попробуйте поискать по слову "mltprcsng"
#basic
Интерактивный поиск по документации Python. Просто наберите имя функции, класса или модуля и сразу получите статью.
Поиск умный, может найти неточное совпадение. Например когда допустили опчепятку в слове. Попробуйте поискать по слову "mltprcsng"
#basic
import sys
print(sys.implementation)
Выполнив этот код, вы увидите некий объект namespace с данными о текущей имплементации интерпретатора.Помимо того что эта информация может быть как-либо полезна давайте обратим внимание на то, что это за объект вообще?
Узнаем что это за тип
>>> type(sys.implementation)
<class 'types.SimpleNamespace'>
SimpleNamespace это простой тип для реализации неймспейса.Если не знаете что такое неймспейс, то представьте себе некий объект-контейнер, куда можно складывать другие объекты. После чего обращаться к ним через имя контейнера. То есть, к имени объекта добавляется дополнительный уровень имени, что и является пространством имён.
По сути, любой модуль и класс является неймспейсом для своего содержимого (если не импортить это содержимое из модуля через "*").
Класс SimpleNamespace позволяет легко добавлять и удалять атрибуты. А также можно передать в конструктор keyword аргументы чтобы сразу создать нужные атрибуты
>>> from types import SimpleNamespace
>>> conf = SimpleNamespace(key1=1, key2=2)
>>> conf.key1
1
>>> setattr(conf, 'key3', 3)
или>>> conf.key3 = 3
>>> conf.key3
3
>>> delattr(conf, 'key2')
или>>> del conf.key2
>>> conf
namespace(key1=1, key3=3)
Вот так можно преобразовать словарь в неймспейс:>>> keys_dict = {'k1': 1, 'k2': 2}
>>> keys = SimpleNamespace(**keys_dict)
>>> keys
namespace(k1=1, k2=2)
Обратное преобразование через vars>>> vars(conf)
{'key1': 1, 'key3': 3}
Как это можно использовать?▫️ красиво оформить "константы" или конфиг. В этом случае, кстати, я бы делал ключи аперкейсом.
>>> conf = SimpleNamespace(
**json.load(config_file.open())
)
>>> conf.API_HOST
"192.168.10.20"
▫️ быстро преобразовать словарь в подобие объекта с доступом к ключам через атрибуты. То есть вместо такой записи: shape['width']
можно будет писать так: shape.width
▫️альтернатива для namedtuple, в которой доступно изменение значения атрибутов.#tricks
🤩 Разбираем полезные исходники!
Функция, возвращающая словарь с данными о панели задач.
🔸 Как может пригодиться?
Я использую для открытия виджета по клику на значке в трее с выравниванием по таскбару. Аналогично работает попап у Dropbox клиента.
🔸 Тестил на Windows10 и Debian10.
🔸 В комплекте проверочный виджет который при создании точно перекрывает таскбар. Проверка правильности определения геометрии таскбара. Закрывается по клику.
🔸 Ещё в комплекте пример окошка, которое появляется в районе часов над таскбаром.
🔸 Есть один баг. При перекрытии тасбара в Gnome (linux) виджет не получает событий от мыши.
Решения пока не нашел😕
Код забираем здесь ↗️
#source #qt
Функция, возвращающая словарь с данными о панели задач.
screen : номер монитораlocation : расположение на экране (внизу, слева и тд)geometry : QRect с координатами таскбараsystem_tray : доступен ли системный трей🔸 Как может пригодиться?
Я использую для открытия виджета по клику на значке в трее с выравниванием по таскбару. Аналогично работает попап у Dropbox клиента.
🔸 Тестил на Windows10 и Debian10.
🔸 В комплекте проверочный виджет который при создании точно перекрывает таскбар. Проверка правильности определения геометрии таскбара. Закрывается по клику.
🔸 Ещё в комплекте пример окошка, которое появляется в районе часов над таскбаром.
🔸 Есть один баг. При перекрытии тасбара в Gnome (linux) виджет не получает событий от мыши.
Решения пока не нашел😕
Код забираем здесь ↗️
#source #qt
Вы используете свойства (
Удобная штука, скажу я вам! Но работают они только для инстансов класса. Вот простой пример:
Как сделать подобие property для класса?
Есть несколько способов:
🔸 Написать свой декоратор в точности повторяющий функционал property. Это ведь не сложно🤓
Я тоже когда-то писал свою версию подобного функционала.
Примеры смотрим здесь↗️ и здесь↗️.
Всё это здорово, но не очень-то хочется изобретать велосипед. Есть ли что-то готовое из стандартных средств?
🔸 Если вы уже перешли на Python 3.9 то можете написать вот так:
Плохая новость — не получится сделать setter, по крайней мере лаконично и красиво.
Например, вот так не работает:
#tricks
@property) в классах?Удобная штука, скажу я вам! Но работают они только для инстансов класса. Вот простой пример:
class A:Создаём класс и получаем значение свойства
@property
def prop(self):
return 10
>>> a = A()А что будет если вызвать свойство у класса
>>> a.prop
10
>>> A.propЭх, несвезло😢
<property object at 0x000...318>
Как сделать подобие property для класса?
Есть несколько способов:
🔸 Написать свой декоратор в точности повторяющий функционал property. Это ведь не сложно🤓
Я тоже когда-то писал свою версию подобного функционала.
Примеры смотрим здесь↗️ и здесь↗️.
Всё это здорово, но не очень-то хочется изобретать велосипед. Есть ли что-то готовое из стандартных средств?
🔸 Если вы уже перешли на Python 3.9 то можете написать вот так:
class С:Например, вот так можно динамический докстринг сделать
@classmethod
@property
def x(cls):
return 2+2
>>> C.x
4
class C:Хорошая новость в том, что это работает из коробки, ничего дописывать не надо.
@classmethod
@property
def __doc__(cls) -> str:
return f"A doc for {cls.__name__!r}"
>>> help(C)
class C(builtins.object)
| A doc for 'C'
...
Плохая новость — не получится сделать setter, по крайней мере лаконично и красиво.
Например, вот так не работает:
class C:Выражение присвоения просто перезаписывает атрибут
_x = 0
def x_get(cls):
return cls._x
def x_set(cls, value):
cls._x = value
x = classmethod(property(x_get, x_set))
x, а не вызывает setter.>>> C.x = 1Чтобы setter тоже работал, нужно сделать иначе. Но об этом смотрите в следующем посте.
>>> C._x
0
#tricks
GitHub
GitHub - mammo0/py-simple-classproperty
Contribute to mammo0/py-simple-classproperty development by creating an account on GitHub.
Продолжаем со свойствами классов. Теперь мы хотим иметь рабочий setter.
🔸 Вместо класса создаем свойства для его мета-класса
🔸 Динамический атрибут класса. Похож на прошлый пример но с дополнительной фишкой.
Что он делает? Этот декоратор не только позволяет добавить свойство класса но и разделить функционал для свойства класса и свойства инстанса.
Работает это через дополнительный вызов
🔸 Вместо класса создаем свойства для его мета-класса
class CMeta(type):При этом можем изменить дефолтное значение для унаследованного класса. Плюс, как и в обычном property можно сделать getter, setter и deleter.
_x = 0
@property
def x(cls):
return cls._x
@x.setter
def x(cls, value):
cls._x = value
class C(metaclass=CMeta):
_x = 2
>>> C.xПроверим, действительно ли сработал setter или мы просто перезаписали атрибут
2
>>> C.x = 34
>>> C.x
34
x
>>> C._xДа, всё верно! 😎
34
🔸 Динамический атрибут класса. Похож на прошлый пример но с дополнительной фишкой.
Что он делает? Этот декоратор не только позволяет добавить свойство класса но и разделить функционал для свойства класса и свойства инстанса.
Работает это через дополнительный вызов
__getattr__ и __setattr__ мета-класса, где требуется проверить имя атрибута и сделать соответствующие выводы.from types import DynamicClassAttribute#tricks
class CMeta(type):
def __getattr__(self, item):
if item == 'x': # проверка имени
return 'x from class'
raise AttributeError
def __setattr__(self, key, value):
print('set class', key, '=', value)
class C(metaclass=CMeta):
@DynamicClassAttribute
def x(self):
return 'x from instance'
@x.setter
def x(self, value):
print('set instance x =', value)
>>> C.x
'from class'
>>> C().x
'from instance'
>>> C.x = 2
'set class x = 2'
C().x = 2
'set instance x = 2'