TGINSIGHT CHAT
Python Заметки
@pythonotes
EducationИнтересные заметки и обучающие материалы по Python Контакт: @paulwinex ⚠️ Рекламу на канале не делаю!⚠️ Хештеги для поиска: #tricks #libs #pep #basic #regex #qt #django #2to3 #source #offtop
Неодамнешни објави
Ознака: #libs · 124 објави
Објавено 22 јул.
Python позволяет передавать любые объекты в качестве аргументов или возвращаемых значений. А так как в Python всё объекты то функции и классы тоже входят в этот список. Но как проверить что нам вернули именно функцию? Не класс, не None и не число и не строку. (Да, динамическая типизация в Python даёт о себе знать) Например, у нас есть функция, полученная из вне. >>> func = some_module.get_function() Надо убедиться что это именно функция. Какие есть варианты? Проверим, вызываемый ли это объект. >>> hasattr(func, '__call__') True Но это ничего не говорит о типе объекта. Вызываемым может быть и класс и генератор и lambda. Лучше всего сравнить тип объекта с типом функции. Но как это сделать? Если бы у нас был int, то всё очевидно: >>> isinstance(value, int) Но где взять ссылку на тип функции? Можно просто забрать его от любой функции >>> # создаём пустую функцию >>> def f():pass >>> # сравниваем типы >>> isinstance(func, type(f)) True Каждый раз нам этого делать не надо. Все нужные типы уже есть в модуле types, созданные именно таким способом. Нам остаётся только сделать сравнение >>> import types >>> isinstance(func, types.FunctionType) True Но есть способ еще проще и понятней, это модуль inspect. Всё тоже самое но завёрнуто красиво. >>> import inspect >>> inspect.isfunction(func) True Приведу неполный но часто используемый мною список функций этого модуля. Функции, определяющие что объект это: .isfunction() — функция .isbuiltin() — стандартная функция Python .isclass() — класс (не инстанс класса) .isabstract() — абстрактный класс .ismethod() — метод класса .isgenerator() — генератор .ismodule() — модуль #libs
Hashtags
Објавено 20 јул.
Регулярно требуется преобразовать какой-либо текст в максимально совместимый текст для URL, имени файла, имени объекта в каком-то софте и тд. Требования совместимости простые: в тексте должны быть только допустимые символы. Обычно это a-z, 0-9 и "_" или "-". То есть, только прописные буквы латинского алфавита и цифры (как пример). Допустим, нам нужно название статьи в блоге преобразовать в slug для добавления его в URL этой статьи. Как это лучше всего сделать? В Django по умолчанию есть готовая функция slugify для таких случаев. Но я её никогда не использую. Почему? Потому что её недостаточно! Приведём пример >>> from django.utils.text import slugify >>> slugify('This is a Title') 'this-is-a-title' Пока всё отлично >>> slugify('This is a "Title!"') 'this-is-a-title' Спец символы удалились, всё хорошо. >>> slugify('Это заголовок статьи') '' Вот и приехали 😢. Если текст не английский то буквы просто игнорируются. Можно это поправить >>> slugify('Это заголовок статьи', allow_unicode=True) 'это-заголовок-статьи' Но тогда мы не вписываемся в условие. У нас появилась кириллица в тексте. Так как я часто пишу сайты для русскоязычных пользователей эта проблема весьма актуальна. Я не использую стандартную функцию и всегда пишу свою. Оригинал я не беру в расчёт и пишу полностью свою функцию. И так, по порядку: 🔸1. Исходный текст: >>> text = 'Мой заголовок №10 😁!' Взял специально посложней со специальными символами. 🔸2. Транслит Необходимо сделать транслит всех символов в латиницу. Здесь очень выручает библиотека unidecode. Помимо простого транслита кириллицы в латиницу она умеет преобразовывать спец символы и иероглифы в текстовые аналоги. from unidecode import unidecode >>> unidecode("Ñ Σ ® µ ¶ ¼ 月 山") 'N S (r) u P 1/4 Yue Shan' Очень крутая библиотека, советую👍 В нашем случае получаем такое преобразование: >>> text = unidecode(text) >>> print(text) 'Moi zagolovok No. 10 !' Отличный транслит. Смайл просто удалился, хотя я ждал что-то вроде :). Ну и ладно, всë равно невалидные символы. А еще наш код уже поддерживает любой язык, будь то хинди или корейский. 🔸4. Фильтр символов Unidecode не занимается фильтрацией по недопустимым символам. Это мы делаем в следующем шаге через regex. Просто заменим все символы на "_" если они вне указанного диапазона. >>> text = re.sub(r'[^a-zA-Z0-9]+', '_', text) >>> print(text) 'Moi_zagolovok_No_10_' Символ "+" в паттерне выручает когда несколько недопустимых символов идут рядом. Все они заменяются на один символ "_". 🔸5. Slugify Осталось удалить лишние символы по краям и сделать нижний регистр >>> text = text.strip('_').lower() >>> print(text) 'moi_zagolovok_no_10' Получаем отличный slug! 😎 🌎 Полный код в виде функции. ______________ PS. Проверку что в строке остался хоть один допустимый символ я бы вынес в отдельную функцию. #libs#tricks#django
Објавено 15 јул.
Так что же такое этот Magic Number? Это набор байтов, уникальный для определённого типа файла. Он еще называется Сигнатура файла. Не каждый файл имеет магическое число, например текстовые файлы в них не нуждаются. По этому набору битов можно точно определить какого типа бинарный файл открыт. Если программе очень важно не перепутать тип файла, то она будет определять его именно по сигнатуре, а не по имени файла. В Python для скомпилированных PYС-файлов магическое число отличается от версии к версии. По нему можно определить версию интерпретатора, которым скомпилирован этот байт-код. Пример библиотеки для определения версии Получить magic number текущей версии можно так: Python 3 >>> from importlib import util >>> util.MAGIC_NUMBER.hex() Python 2 >>> import imp >>> imp.get_magic().encode('hex') Интерпретатор использует это значение для проверки PYC-файлов перед импортом. Если версия не подходящая вы увидете ошибку: RuntimeError: Bad magic number in .pyc file То есть, помимо типа файла, магическое число может также обозначать разные версии одного типа. Итого, сигнатура файла помогает: 🔸 быстро определить формат файла вне зависимости от имени (например для запуска соответствующего приложения в OS) 🔸 обозначать совместимость одного и того же бинарного формата с разными версиями софта (пошло из Unix систем) 🔸разделить бинарники программ по вариантам сборки 🔸 восстанавливать файлы при потере таблицы файлов диска 🔸 использовать быстрый поиск файлов по типу без обращения к таблице файлов 🔸 получить типа файла, передаваемого по сети, не качая его целиком Список этим, конечно же, не ограничивается. #libs#tricks
Објавено 13 јул.
fleep не поддерживает нужный тип файла? Не нашли подходящую сигнатуру в интернете? Тогда пробуйте ➡️puremagic, еще больше типов! Возможно самая актуальная библиотека по данной теме. Всё ещë нет нужной сигнатуры? Видимо, у вас сложный случай. Остаëтся только найти "магическое число" вашего файла самостоятельно. Делается это достаточно просто. Нужно посмотреть на файл в шестнадцатеричном представлении. Первые биты файла будут вашим искомым значением. Для просмотра можно использовать: 🔸mcedit. Редактор который идёт в поставке с mc (Linux). Жмем F3 для просмотра и сразу F4 для переключения режима. 🔸xxd (что это?) Пример для Linux xxd myfile.ext | head head не даёт прочитать весь файл. Нам нужно лишь начало. Для Windows тот же xxd, который идет в поставке с Git ...\Git\usr\bin\xxd.exe -l 100 myfile.ext Флаг "l" аналогичен head на Linux Теперь проходимся по нескольким файлам этого формата и ищем совпадающие первые биты, которые всегда одинаковы. Нужное число найдено! #libs#tricks
Објавено 10 јул.
Вы прониклись идеей определять тип файла не по расширению из имени а по содержимому (по сигнатуре или по magic number)? Не хватает стандартных библиотек imghdr и sndhdr? Тогда специально для вас есть решение — библиотека fleep Только посмотрите на количество поддерживаемых форматов. Изображения, звук, видео, документы, шрифты, 3D пакеты... На данный момент 104 формата! Стоит заметить, что: 🔸 автор скорее всего разрабатывал её на Windows 10, стоит хорошо проверить её перед использованием на других платформах. 🔸 добавление новых форматов происходит через обновления JSON файла, но я бы сделал под каждый формат отдельный файл. Просто так удобней расширять список форматов не изменяя исходников. 🔸 Список сигнатур файлов для добавления можно найти в интернете, например на вики: https://ru.wikipedia.org/wiki/Список_сигнатур_файлов 🔸 На хабре есть статья от автора https://habr.com/ru/post/345822/ PS. Также можете взглянуть на filetype #libs
Hashtags
Објавено 9 јул.
Аналогично imghdr в Python есть стандартная утилита sndhdr. Определение форматов аудио файлов! Тест этой библиотеки возвращает не просто формат в виде строки, а именованный кортеж с дополнительными данными о файле. Например длительность, количество каналов или частота семплирования. Поддерживаются следующие форматы: aifc aiff au hcom sndr sndt voc wav 8svx sb ub ul Эммм... а где же MP3? Где Flac??? Может они не вписываются в концепцию библиотеки по каким-либо признакам? Или это задел на развитие? Программисты не используют MP3? (Только WAV, только хардкор!) Даже в исходниках есть вопрос без ответа... #libs
Hashtags
Објавено 7 јул.
Когда-то давно, когда я сел за компьютер примерно третий раз в жизни, я изобрёл... самый быстрый и универсальный конвертор форматов изображений🤓 Схематично он довольно просто (ведь всё гениальное просто): rename my_image.bmp -> my_image.jpg Ох уж это наивное IT-детство))) Я действительно думал что победил систему. Если Paint открыл, то значит конвертация прошла успешно! 😭 Если вы пишете какую-то программу работы с изображениями, то порой бывает полезно защититься от таких "гениальных" разработок и однозначно понимать какого типа файл перед вами независимо от его имени. В этом вам поможет стандартная библиотека imghdr. По умолчанию она понимает следующие форматы: rgb gif pbm pgm ppm tiff rast xbm jpeg bmp png webp exr Вы всегда можете добавить свой формат. Для этого в список imghdr.tests нужно добавить функцию проверки с определённым набором аргументов: байты и открытый файл. Вернуть функция должна либо строку с типом формата либо None. Пример проверки файла с изменённым расширением >>> import imghdr >>> imghdr.what('image.png') 'jpeg' Как же происходит проверка? Очевидно, что не на основе расширения файла. Каждый тип файла содержит заранее известный паттерн данных (magic number). Функции проверки просто ищут этот паттерн в бинарных данных файла. Если совпадение есть, то формат определён. Всё станет понятно когда посмотрите исходники этого модуля. Код тестов состоит из 2-3 строк, при этом одна из них это return. #libs
Hashtags
Објавено 29 јун.
Для тех кто бегло просмотрел материал прошлого поста. Вы могли не заметить ссылку на крутую библиотеку Urwid! Это обертка для curses, реализующая интерфейс для создания оконных GUI в терминале😳! С этой библиотекой вы оперируете не символами и их атрибутами, а виджетамиилейаутами! Почти как в PyQt, только для терминала. При этом с виджетами можно взаимодействовать с помощью мыши. Посмотрите примеры чтобы иметь представление о возможностях. 🌎 Моё меню из прошлого поста, переделанное на Urwid Это меню понимает клики мышкой. #libs
Hashtags
Објавено 26 јун.
Признавайтесь, кто хотел бы написать свой vim из которого можно легко выйти? ))) Это не так сложно как может показаться. По крайней мере движок для интерфейса уже есть в Python из коробки! Это библиотека curses! Для Windows она не идет в поставке. Нужно установить windows-curses pip install windows-curses Эта библиотека превращает терминал в "ASCII canvas" и можете "рисовать" в нём с помощью любых символов что пожелаете! Что можно сделать? Вот несколько идей: 🖥 Крутое меню для вашего CLI 📝 Свой текстовый редактор в терминале (vim, nano) 📺 Оконный интерфейс в терминале (Norton Commander, Midnight Commander) 🐍 Игра на базе терминала (тетрис, карты, змейка) /Каждый питонист должен написать "Змейку"! / 📊 Приложение с анимированными элементами статистики (htop) 🚀 Свой REPL c блекджеком и автокомплитами (bpython, ptpython) __________________ 🌎 Мои эксперементы за вечер, простое меню для выбора действий. А это мануал на devdungeon.com для тех кто хочет проникнуться этой темой #libs
Hashtags
Објавено 24 јун.
Как быстро распечатать красиво время имея в наличии число секунд ⏱? Конечно, можно посчитать сколько в этих секундах минут, часов и потом посчитать остаток, но есть способ быстрей! Это стандартный класс datetime.timedelta Просто создайте класс с указанием того что у вас есть и конвертните его в строку. Он всё посчитает за вас и покажет стандартный формат времени. >>> from datetime import timedelta >>> str(timedelta(seconds=1024)) '0:17:04' Можно просто распечатать если результат нужен в консоли >>> print(timedelta(minutes=128)) 2:08:18 Также поддерживаются нецелые значения. Например, нецелое число минут будет преобразовано в секунды. >>> print(timedelta(minutes=256.5)) 4:16:30 Вот так можно распечатать полтора часа >>> print(timedelta(hours=1.5)) 1:30:00 Можно выходить за пределы одних суток, появится количество дней >>> print(timedelta(hours=64.32)) 2 days, 16:19:12 >>> print(timedelta(weeks=20.32)) 142 days, 5:45:36 А еще они поддерживают математические операции >>> print(timedelta(minutes=5) + timedelta(hours=2)) 2:05:00 #libs#tricks
Објавено 22 јун.
Наверняка вы слышали о самом простом способе установить PIP, это скрипт get-pip.py. Скачиваем его, скармливаем интерпретатору и PIP установлен! python get-pip.py Но что это...??? Скрипт размером 1.8 МБ? Я думаю вы уже догадались почему. Смотрим докстринг в начале файла: ... This is a base85 encoding of a zip file, this zip file contains an entire copy of pip (version ХХ.Х.Х) ... Да, в скрипте сохранён ZIP архив! Он закодирован с помощью base85(аналог base64) записан в переменной DATA. Если вы сомневались что данный способ хранения данных бывает полезен, то вот вам яркий пример удобного инструмента на его основе. Один простой файл в котором есть всё что ему нужно 😎 #libs
Hashtags
Објавено 19 јун.
Ещё немного про base64. Собрал пример со встроенной в код картинкой. Это иконка для окна на PySide2. Файл кодирован в base64 и просто сохранён в переменной. Для использования этих данных даже не пришлось сохранять их в новый файл. Иконка создаётся на лету с помощью метода QPixmap.loadFromData() ... raw_data = base64.decodebytes(ico_encoded) ico = QPixmap() ico.loadFromData(raw_data, "PNG") ... 🌎 Полный пример смотрите в gists. #libs#tricks#qt