Python Заметки
2.32K subscribers
58 photos
2 videos
2 files
212 links
Интересные заметки и обучающие материалы по Python

Контакт: @paulwinex

⚠️ Рекламу на канале не делаю!⚠️

Хештеги для поиска:
#tricks
#libs
#pep
#basic
#regex
#qt
#django
#2to3
#source
#offtop
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
rich

Библиотека для нескучного принта!
Добавляет в ваш терминал цвет и разные способы форматирования текста.

https://github.com/willmcgugan/rich

➡️ Мой небольшой пример

#libs
👍10
Новый пакеджинг для Python uv написанный на Rust от автора быстрого линтера Ruff

Что нам обещают

▫️ Эпичная скорость
▫️ Легкий переход с pip и pip-tools
▫️ Отсутствие зависимостей и дистрибуция в виде одного автономного bin файла

Следим, надеемся, тестируем...

#libs
🔥9🤔1
Библиотека psutil предоставляет весьма широкий инструментарий для взаимодействия с процессами.
Одна из полезных функций - узнать какие файлы открыты в контексте процесса или узнать какой процесс занимает файл.

Узнаём какие файлы использует процесс

import psutil
def list_file_handlers(process_name):
for proc in psutil.process_iter():
if proc.name().lower().startswith(process_name):
for file in proc.open_files():
print(file)
list_file_handlers('python')

Функция вернёт имя процесса который занял файл. Если файл не занят то вернёт None.

def who_is_use(fpath):
for proc in psutil.process_iter():
for item in proc.open_files():
if fpath == item.path:
return proc.name()


Для использования требуются админские права.

#libs
6👍4
Библиотека APScheduler для управления заданиями в Python.
Может запускать планировщик и задания как отдельный поток (синхронный код) и как коркутины (асинхронный код), отложенные или через интервал.

Что есть в APScheduler:

▫️гибкий функционал создания задачи
▫️удобное управление созданными заданиями (pause\resume, listing, modify, reschedule)
▫️кастомизация классов библиотеки
▫️различные хранилища заданий (Memory и различные БД)
▫️интеграции в фреймворки
▫️7 вариантов планировщика

Три варианта тригеров для задач:

▫️по дате с помощью datetime
▫️через интервал с помощью datetime
▫️через интервал с помощью cron

и другие полезности

В данный момент готовится к релизу 4я версия

PS. Всегда использую вместе с FastAPI, очень рекомендую к ознакомлению.

#libs
🔥4👍2
POSIX (Portable Operating System Interface) — это набор стандартов, определяющих интерфейсы для обеспечения совместимости между операционными системами.
Данный стандарт поддерживается всеми UNIX-системами (GNU/Linux, macOS, FreeBSD, OpenBSD и другие). А вот в Windows либо частично, либо через подсистемы (такие как WSL).

Помимо прочих условий, один из важных моментов этого стандарта - правила синтаксического анализа строк, разбиение на токены.

В Python разбиением строки на токены занимается функция shlex.split(), которая имеет один важный аргумент - posix.
Этот аргумент определяет, следует ли функции использовать правила синтаксического анализа соответствующие стандарту POSIX, или использовать обратно совместимый, легаси режим.

▫️posix=True

В POSIX-совместимом режиме функция shlex.split() будет учитывать переменную окружения IFS (Internal Field Separator) для определения разделителей полей и будет более строго следовать стандарту POSIX. Из строки удаляются неэкранированные кавычки и обратные слеши.

▫️posix=False

В легаси режиме используется более старый способ разбиения строк на токены, который будет игнорировать переменную окружения IFS и использовать whitespaces как разделители полей.

Теперь смотрим некоторые примеры.
import shlex
# кавычки
text = r'"Do"Not"Separate" \"This\"'
shlex.split(text, posix=False)
# ['"Do"', 'Not"Separate"', '\\"This\\"']
shlex.split(text, posix=True)
# ['DoNotSeparate', '"This"']

# специсимволы
text = r'A\tB\nС\fD\vE'
shlex.split(text, posix=False)
# ['A\\tB\\nС\\fD\\vE']
shlex.split(text, posix=True)
# ['AtBnСfDvE']

# обратный слеш
text = r"cmd.exe c:\games\mario.exe"
shlex.split(text, posix=False)
# ['cmd.exe', 'c:\\games\\mario.exe']
shlex.split(text, posix=True)
# ['cmd.exe', 'c:gamesmario.exe']

Учитвая, что аргумент posix по умолчанию True, стоит помнить этот факт при обработке строк с Windows-путями!

Рекомендую самостоятельно поэксперементировать с этим аргументом!

#libs
👍71
Unofficial Windows Binaries for Python Extension Packages - известная страница с множеством скомпилированных python-библиотек для Windows. Её вёл Christoph Gohlke и любезно нам собирал whl пакеты. Очень часто эа страница помогала и мне и, вероятно, многим из вас.

В июне 2022 года из-за отсутствия финансирования проект был закрыт и обновления долго не выходили. Позже и страница была удалена😭

В начале 2023 года Christoph Gohlke создал репозитории на GitHub которые заменили этот "сервис". На его странице в самом верху можно найти несколько ссылок на эти репозитории.

В частности репозиторий Pymol-open-source wheels for Python on Windows. Не могу сказать что это уже полноценная замена, кажется новые библиотеки добавляются неспеша, но это уже что-то. Активность можете проследить самостоятельно.

А еще там есть эксперементальные сборки для ARM64.

PS. Если знаете где есть подобные архивы, поделитесь в коментах.

#libs
🔥3
Когда требуется быстро расшарить файлы в локальную сеть со своего компа можно использовать дефолтный python-сервер. Все решается одной командой.

python3 -m http.server


Но это бывает неудобным если нужно скачать папку или залить файлы. В этом случае более удобным будет быстрый FTP сервер.

Я себе сделал шорткат для поднятия простого FTP сервера без авторизации на базе библиотеки pyftpdlib.

Варианты запуска:

# на рандомном порту read only
python3 -m pyftpdlib

# на указанном порту
python3 -m pyftpdlib -p 22222

# с доступом на запись
python3 -m pyftpdlib -w

# с авторизацией
python3 -m pyftpdlib -w --user=name --password=123

# полный список аргументолв
python3 -m pyftpdlib -h


Мой алиас для расшаривания в текущей директории

alias ftp="python3 -m pyftpdlib -w -p 22222"


Теперь можно подключть FTP соединение как удалённую директорию стандартными средствами OS. В Windows это Add Network Location, в Linux - зависит от дистрибутива. Ищите в разделе Network вашего файлового браузера.
Также можно использовать сторонние клиенты, например FileZilla.

А здесь подробней про http.server

#libs #tricks
🔥12👏2👍1
А вот и наглядное использование контроля стилей через свойства виджета. Билиотека qt-material.

В этом разделе написано, что через свойство class можно контролировать цвет кнопки, по аналогии с css стилями.

btn_danger.setProperty('class', 'danger')
btn_warning.setProperty('class', 'warning')
btn_success.setProperty('class', 'success')


#libs #qt
👍3🔥2
JSON API сейчас весьма актуален в сфере веб-приложений.
Но у стандартной библиотеки json есть проблема - она относительно медленная.

Если ваше веб приложение должно тянуть держать нагрузку, то такие популярные операции как сериализация и десериализация JSON хорошо бы максимально оптимизировать. Каждый запрос это преобразование JSON-строки в объект, обработка запроса, и обратное кодирование объекта в JSON-строку. Буквально - каждый!

Исходные данные для теста:
file = 'data.json'  # 156kb
with open(file, 'r') as f:
file_data = f.read()
data = json.loads(file_data)
count = 50000

Сделаем эталонный замер стандартной библиотеки
start = time.perf_counter()
for i in range(count):
json.loads(file_data)
end = time.perf_counter()
json_time_decode = end - start

start = time.perf_counter()
for i in range(count):
json.dumps(data)
end = time.perf_counter()
json_time_encode = end - start

print(f'Json time: {round(json_time_decode, 2)}s/{round(json_time_encode)}s')
# Json time: 50.04s/40s

Итак, какие есть альтернативы?

Сравнивать будем с библиотеками orjson и ujson.
Код находится на github, а здесь приведу только результаты.
Json time: 50.04s/40s
Orjson time: 20.27s [2.47x speed] / 5.46s [7.35x speed]
Ujson time: 47.29s [1.06x speed] / 35.04s [1.15x speed]

Неплохой прирост с orjson я считаю! А вот ujson не особо опередил.

Тест проводился на Windows 10. Интересно, что на Linux ujson даже медленней чем стандартный. Но, думаю, это у меня какие-то проблемки.

В тесты я не добавил simplejson. Он не сильно быстрей стандартного модуля.

Если вы пишете приложения на FastAPI, то в 3 строки можете ускорить обработку JSON-ответа! Есть встроенный класс для этого.

1. Установка
poetry add orjson
# or
pip install orjson

2. Имопрт
from fastapi.responses import ORJSONResponse 
# Там же лежит и UJSONResponse

3. Подключение
app = FastAPI(
...
default_response_class=ORJSONResponse
)


Для Django тоже есть решение: drf-orjson-renderer

#libs
🔥64👍2
Pyrogram закрылся!

Популярная библиотека pyrogram больше не будет развиваться. 24-го декабря мейнтейнер перевёл репозиторий в архив и написал сообщение с разъяснениями.

Если вы используете pyrogram в своих проектах, то у меня для вас плохая новость. Когда в Telegram появятся новые функции или изменится API, ваш проект перестанет работать. Рекомендую оперативно его переписывать.

Актуальная альтернатива - Telethon
➡️ https://github.com/LonamiWebs/Telethon

Документация здесь
📖 https://docs.telethon.dev/en/stable/

#libs
😱3😢21
Использование Pydantic сегодня стало нормой, и это правильно. Но иногда на ревью вижу, что используют его не всегда корректно.
Например, метод BaseModel.model_dump() по умолчанию не преобразует стандартные типы, такие как datetime, UUID или Decimal, в простой сериализуемый для JSON вид. Тогда пишут кастмоный сериализатор для этих типов чтобы функция json.dump() не падала с ошибкой.

import uuid
from datetime import datetime
from decimal import Decimal
from uuid import UUID
from pydantic import BaseModel

class MyModel(BaseModel):
id: UUID
date: datetime
value: Decimal


obj = MyModel(
id=uuid.uuid4(),
date=datetime.now(),
value='1.23'
)
print(obj.model_dump())
# не подходит для json.dump
# {
# 'id': UUID('4f8c1bc4-25fd-40cd-9dbe-2c73639b0dc1'),
# 'date': datetime.datetime(2025, 12, 12, 12, 12, 12, 111111),
# 'value': Decimal('1.23')
# }
# добавляем свой кастомный сериализатор
json.dumps(obj.model_dump(), cls=MySerializer)
# {
# 'id': '4f8c1bc4-25fd-40cd-9dbe-2c73639b0dc1',
# 'date': '2025-12-12T12:12:12.111111',
# 'value': '1.23'
# }


В данном случае класс MySerializer обрабатывает datetime, UUID и Decimal. Например так:
class MySerializer(json.JSONEncoder):
def default(self, o):
if isinstance(o, Decimal):
return str(o)
elif isinstance(o, datetime):
return o.isoformat()
elif isinstance(o, UUID):
return str(o)
return super().default(o)


Специально для тех, кто всё еще так делает - в этом нет необходимости!
Pydantic может это сделать сам, просто нужно добавить параметр mode="json".
json.dumps(obj.model_dump(mode="json"))
# {
# 'id': '4f8c1bc4-25fd-40cd-9dbe-2c73639b0dc1',
# 'date': '2012-12-12T12:12:12.111111',
# 'value': '1.23'
# }


#pydantic #libs
8👍6🔥4