Когда требуется быстро расшарить файлы в локальную сеть со своего компа можно использовать дефолтный python-сервер. Все решается одной командой.
Но это бывает неудобным если нужно скачать папку или залить файлы. В этом случае более удобным будет быстрый FTP сервер.
Я себе сделал шорткат для поднятия простого FTP сервера без авторизации на базе библиотеки pyftpdlib.
Варианты запуска:
Мой алиас для расшаривания в текущей директории
Теперь можно подключть FTP соединение как удалённую директорию стандартными средствами OS. В Windows это Add Network Location, в Linux - зависит от дистрибутива. Ищите в разделе Network вашего файлового браузера.
Также можно использовать сторонние клиенты, например FileZilla.
А здесь подробней про http.server
#libs #tricks
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
GitHub
GitHub - giampaolo/pyftpdlib: Extremely fast and scalable Python FTP server library
Extremely fast and scalable Python FTP server library - giampaolo/pyftpdlib
🔥12👏2👍1
А вот и наглядное использование контроля стилей через свойства виджета. Билиотека qt-material.
В этом разделе написано, что через свойство class можно контролировать цвет кнопки, по аналогии с css стилями.
#libs #qt
В этом разделе написано, что через свойство 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-строку. Буквально - каждый!
Исходные данные для теста:
Сделаем эталонный замер стандартной библиотеки
Итак, какие есть альтернативы?
Сравнивать будем с библиотеками orjson и ujson.
Код находится на github, а здесь приведу только результаты.
Неплохой прирост с orjson я считаю! А вот ujson не особо опередил.
Тест проводился на Windows 10. Интересно, что на Linux ujson даже медленней чем стандартный. Но, думаю, это у меня какие-то проблемки.
В тесты я не добавил simplejson. Он не сильно быстрей стандартного модуля.
Если вы пишете приложения на FastAPI, то в 3 строки можете ускорить обработку JSON-ответа! Есть встроенный класс для этого.
1. Установка
2. Имопрт
3. Подключение
Для Django тоже есть решение: drf-orjson-renderer
#libs
Но у стандартной библиотеки 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
GitHub
GitHub - ijl/orjson: Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy
Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy - ijl/orjson
🔥6❤4👍2
Pyrogram закрылся!
Популярная библиотека pyrogram больше не будет развиваться. 24-го декабря мейнтейнер перевёл репозиторий в архив и написал сообщение с разъяснениями.
Если вы используете pyrogram в своих проектах, то у меня для вас плохая новость. Когда в Telegram появятся новые функции или изменится API, ваш проект перестанет работать. Рекомендую оперативно его переписывать.
Актуальная альтернатива - Telethon
➡️ https://github.com/LonamiWebs/Telethon
Документация здесь
📖 https://docs.telethon.dev/en/stable/
#libs
Популярная библиотека pyrogram больше не будет развиваться. 24-го декабря мейнтейнер перевёл репозиторий в архив и написал сообщение с разъяснениями.
Если вы используете pyrogram в своих проектах, то у меня для вас плохая новость. Когда в Telegram появятся новые функции или изменится API, ваш проект перестанет работать. Рекомендую оперативно его переписывать.
Актуальная альтернатива - Telethon
➡️ https://github.com/LonamiWebs/Telethon
Документация здесь
📖 https://docs.telethon.dev/en/stable/
#libs
😱3😢2❤1
Использование Pydantic сегодня стало нормой, и это правильно. Но иногда на ревью вижу, что используют его не всегда корректно.
Например, метод
В данном случае класс
Специально для тех, кто всё еще так делает - в этом нет необходимости!
Pydantic может это сделать сам, просто нужно добавить параметр
#pydantic #libs
Например, метод
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
❤9👍7🔥5
В работе с медиа файлами часто требуется определить не просто расширение, а его, скажем так, "категорию". Тоесть определить это видео, аудио или картинка. Примерно в 10 случаях из 10 в ревью я вижу обычный хардкодинг с большим мапингом и соответствующим поиском по нему.
Для таких случаев есть простой способ - стандартная библиотека
Причём ей не нужен файл, достаточно просто имени строкой.
Первый элемент кортежа это MIME-тип (Multipurpose Internet Mail Extensions Type) - стандартный способ идентификации формата файла.
Формат:
Второй элемент это тип кодировки содержимого, обычно для контейнеров типа gz и аналогичных.
Итого, узнать категорию файла одной строкой:
Конечно при условии, что тип будет распознан, иначе будет
#libs #tricks
file_type_by_ext = {
'video': ['.mp4', '.mov', '.mkv', ...],
'audio': ['.mp3', '.wav', '.ogg', ...],
'image': ['.jpg', '.png', '.exr', ...]
}Для таких случаев есть простой способ - стандартная библиотека
mimetypes.import mimetypes
mimetypes.guess_type("example.txt")
# ('text/plain', None)
Причём ей не нужен файл, достаточно просто имени строкой.
Первый элемент кортежа это MIME-тип (Multipurpose Internet Mail Extensions Type) - стандартный способ идентификации формата файла.
Формат:
type/subtypetype - общая категория данных (text, video, image)subtype - конкретный формат внутри категорииmimetypes.guess_type("photo.jpg")
# ('image/jpeg', None)
mimetypes.guess_type("render.mp4")
# ('video/mp4', None)Второй элемент это тип кодировки содержимого, обычно для контейнеров типа gz и аналогичных.
mimetypes.guess_type("file.tar.gz")
# ('application/x-tar', 'gzip')
mimetypes.guess_type("backup.tar.bz2")
# ('application/x-tar', 'bzip2')Итого, узнать категорию файла одной строкой:
mimetypes.guess_type('myfile.mov')[0].split('/')[0]
# videoКонечно при условии, что тип будет распознан, иначе будет
None а не строка. Но об этом в следующий раз.#libs #tricks
👍19
import mimetypes
mimetypes.guess_type("example.fbx")
# (None, None)
Формат не распознан, так как не зарегистрирован в системе.
Регистрация происходит с помощью функции
mimetypes.init(). Эта функция автоматически вызывается при первом обращении.Для каждой OS работает по-разному. В Windows читает реестр, в Linux достает всё из файла
/etc/mime.types, в MacOS читает из системной БД.На linux можно попробовать распознать тип через вызов
file --mime-type -b <filename>
эта команда попробует прочитать метадату самого файла, то есть должен быть доступ к файлу. Но это не гарантия успеха.
Можно попробовать использовать нестрогое соответствие IANA с помощью флага
strict=False. Тогда будут учтены старые и нестандартные типы. Обычно они с префиксом x-Новые типы можно добавлять самостоятельно.
mimetypes.add_type('application/x-fbx', '.fbx') # с точкой
mimetypes.guess_type("example.fbx")
# ('application/x-fbx', None)Либо вызвать
init() еще раз передав список текстовых файлов с нужными вам типами (без точки)# my-mime-types.txt
application/x-fbx fbx
application/x-ogo ogo
application/x-aga aga
mimetypes.init(['my-mime-types.txt'])
mimetypes.guess_type("example.ogo")
# ('application/x-ogo', None)
Есть и обратная операция - получить расширение файла из mime-типа
mimetypes.guess_extension('image/jpeg')
# .jpgИли все подходящие расширения
mimetypes.guess_all_extensions('image/jpeg')
# ['.jpg', '.jpe', '.jpeg', '.jfif']Советую почитать полную документацию
Также обратите внимание на библиотеку content-types для работы с mime-типами, где больше возможностей.
#libs #tricks
🔥4