fa
Feedback
Коробка с питоном

Коробка с питоном

رفتن به کانال در Telegram

Заметки от Python-разработчика: сниппеты, обзоры пакетов, новости и другая полезная информация. Автор: @kiriharu

نمایش بیشتر
462
مشترکین
-124 ساعت
اطلاعاتی وجود ندارد7 روز
-530 روز

در حال بارگیری داده...

ابر برچسب‌ها
هیچ داده‌ای
مشکلی وجود دارد؟ لطفاً صفحه را تازه کنید یا با مدیر پشتیبانی ما تماس بگیرید.
اشارات ورودی و خروجی
---
---
---
---
---
---
جذب مشترکین
دسامبر '24
دسامبر '240
در 0 کانال‌ها
نوامبر '24
+7
در 0 کانال‌ها
Get PRO
اکتبر '24
+4
در 0 کانال‌ها
Get PRO
سپتامبر '24
+10
در 0 کانال‌ها
Get PRO
اوت '24
+4
در 0 کانال‌ها
Get PRO
ژوئیه '24
+9
در 0 کانال‌ها
Get PRO
ژوئن '24
+6
در 0 کانال‌ها
Get PRO
مه '24
+24
در 1 کانال‌ها
Get PRO
آوریل '24
+9
در 0 کانال‌ها
Get PRO
مارس '24
+15
در 0 کانال‌ها
Get PRO
فوریه '24
+19
در 0 کانال‌ها
Get PRO
ژانویه '24
+39
در 0 کانال‌ها
Get PRO
دسامبر '23
+20
در 0 کانال‌ها
Get PRO
نوامبر '23
+18
در 0 کانال‌ها
Get PRO
اکتبر '23
+31
در 1 کانال‌ها
Get PRO
سپتامبر '23
+17
در 0 کانال‌ها
Get PRO
اوت '23
+40
در 0 کانال‌ها
Get PRO
ژوئیه '23
+12
در 0 کانال‌ها
Get PRO
ژوئن '23
+25
در 0 کانال‌ها
Get PRO
مه '23
+4
در 0 کانال‌ها
Get PRO
آوریل '23
+8
در 0 کانال‌ها
Get PRO
مارس '23
+3
در 0 کانال‌ها
Get PRO
فوریه '23
+12
در 0 کانال‌ها
Get PRO
ژانویه '23
+8
در 0 کانال‌ها
Get PRO
دسامبر '22
+8
در 0 کانال‌ها
Get PRO
نوامبر '22
+21
در 0 کانال‌ها
Get PRO
اکتبر '22
+14
در 0 کانال‌ها
Get PRO
سپتامبر '22
+3
در 0 کانال‌ها
Get PRO
اوت '22
+5
در 0 کانال‌ها
Get PRO
ژوئیه '22
+4
در 0 کانال‌ها
Get PRO
ژوئن '22
+9
در 0 کانال‌ها
Get PRO
مه '22
+12
در 0 کانال‌ها
Get PRO
آوریل '22
+59
در 0 کانال‌ها
Get PRO
مارس '22
+4
در 0 کانال‌ها
Get PRO
فوریه '22
+6
در 0 کانال‌ها
Get PRO
ژانویه '22
+5
در 0 کانال‌ها
Get PRO
دسامبر '21
+13
در 0 کانال‌ها
Get PRO
نوامبر '21
+3
در 0 کانال‌ها
Get PRO
اکتبر '21
+28
در 0 کانال‌ها
Get PRO
سپتامبر '21
+286
در 0 کانال‌ها
تاریخ
رشد مشترکین
اشارات
کانال‌ها
21 دسامبر0
20 دسامبر0
19 دسامبر0
18 دسامبر0
17 دسامبر0
16 دسامبر0
15 دسامبر0
14 دسامبر0
13 دسامبر0
12 دسامبر0
11 دسامبر0
10 دسامبر0
09 دسامبر0
08 دسامبر0
07 دسامبر0
06 دسامبر0
05 دسامبر0
04 دسامبر0
03 دسامبر0
02 دسامبر0
01 دسامبر0
پست‌های کانال
Сегодня у нас простенькая задачка, а то пятница, все отдыхать хотят, я понимаю. Есть следующий код:
def test():
  try:
    return 1
  finally:
    return 2
Вопрос - что вернется при вызове test()? Все и так на этом моменте понимают, что вернётся 2 (ну не просто так же мы собрались, верно?), но почему? Ответ, как обычно, есть в документации. Возвращаемое функцией значение определяется последним выполненным return. Вторым важным аспектом является то, что finally исполняется всегда, поэтому мы и получаем его return. raise, кстати, тоже работать не будет:
def test():
  try:
    raise ValueError()
  finally:
    return 3 

test() # 3
#std #задачки

2
Решил канал расширить ещё одной тематикой - занимательными задачками. Пока что буду писать про те, которые встречались на тех. собеседованиях. Они не всегда будут адекватные, но что уж есть :) А начнём, как полагается с классики. Надо объяснить следующее поведение: >>> a = 256 >>> b = 256 >>> a is b True # ??? >>> a = 257 >>> b = 257 >>> a is b False # ??? Вопрос в том, что здесь творится с ссылками. Разберём самую первую часть. Пробуем получить id объектов: >>> a = 256 >>> b = 256 >>> id(a), id(b) (2214170730704, 2214170730704) На вопрос, почему у них одинаковые идентификаторы ответит деталь реализации PyLong_FromLong (для искушенных читать можно читать отсюда), которая указывает, что интерпретатор хранит массив целочисленных объектов для всех чисел в диапазоне от -5 до 256. Поэтому, когда мы создаем переменную с числом в этом диапазоне он просто отдает ссылку на уже существующий объект. Микрооптимизация, при чём очень важная - так уж получилось что числа из этого диапазона используются чаще всего. В Java есть похожая оптимизация, там такой диапазон составляет от -128 до 127, но есть нюансы. Второй вопрос отпадает сам собой (будут разные ссылки), но что будет если мы создадим файл с следующим содержимым и запустим его: a = 257 b = 257 print(a is b) # True А вот это уже нюанс работы нашего REPL. Каждая написанная нами строка в нём разбирается отдельно. Но при запуске через файл Python имеет возможность применить дополнительные оптимизации для констант, так как он видит сразу весь код - в этом и различие. #std #задачки
0
3
Да, у нас есть тесты. А толку? Супер-мега-гига экслюзивный доступ к записи моего доклада с прошедшего PiterPy. Организаторы разрешили выложить не дожидаясь следующего года. Получилось как всегда холиварно, не всё всем может понравиться, но как минимум советую присмотреться к библиотечкам и статьям/докладам из полезных ссылок. Там немного, но самое годное из того что знаю по этой теме. Куда кидать помидоры и звездочки вы знаете 🙂🙃 https://youtu.be/liECQCFGfkE
0
4
PSF и JetBrains запустили своё ежегодное исследование Python Developers Survey 2023. Погнали заполнять! 👇 https://survey.alchemer.com/s3/7554174/python-developers-survey-2023 Через год, когда подведут результаты, будет повод написать пост, типа такого 😅
0
5
В одном чатике встретил забавный проект fakeredis, реализующий Redis-сервер на питоне, который можно использовать для тестов. Очевидно, чтобы не таскать для тестов настоящий Redis. Поддерживаются практически все стандартные команды, которые я встречал для работы с коллекциями (список здесь). Есть не полная поддержка JSON, поиска, time series. Если каких-то команд не хватает, автор оставил гайд, как её сделать. Ну а если сделаете - законтрибутьте в опенсорс, полезное дело всё таки! #библиотека
0
6
На сегодня расскажу ещё пару рецептов с more_itertools. 1) map_if работает как обычный map, но применяет функцию на элемент только если оно попадает под условие. Например, вот так мы можем возвести в квадрат только те числа, которые делятся на 2 нацело: example = [1, 2, 3, 4, 5, 6, 7, 8] list(map_if(example, lambda x: x % 2 == 0, lambda x: x * x)) # [1, 4, 3, 16, 5, 36, 7, 64] 2) Получить последний элемент можно при помощи last. Возникает вопрос а зачем он существует, если можно указать iterable[-1]? Ответом является то, что last позволяет указать, что ему возвращать, если элементов в итерируемом объекте нет: last([1, 2, 3]) # Очевидно получим 3 last([], 0) # Список пустой, но получим 0 [][-1] # Получим IndexError Ещё есть first - как понятно из названия, он получает первый элемент. 3) map_except тоже работает как map, но умеет игнорировать ошибки. Например, мы хотим получить только те элементы, которые получилось привести к целому числу: example = [1, "1", "2", "test", "three", object, 4.0] list(map_except(int, example, ValueError, TypeError)) # [1, 1, 2, 4] 4) Ну и в конце про take - он просто берет N элементов из итерируемого объекта: example = range(10) take(3, example) # [0, 1, 2] take(20, example) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - если больше, возьмет доступные #itertools #more_itertools #библиотека
0
7
Пока я спал, руководящий совет языка принял PEP 703 (nogil). Кратко о том, о чём говорится в посте: 1. Руководящему совету ясно, что несмотря на все проблемы и недостатки потоков, nogil будет полезен для Python, так как позволит находить более масштабируемые решения. 2. В то же время, они не уверены, получится ли убрать GIL не сломав при этом обратную совместимость - всё же не хотелось бы терять десятилетия развития базы пакетов. Существующая пакетная экосистема - это одна из сильных сторон языка, как и простая интеграция библиотек на C c CPython. 3. Оценить влияние nogil без реализации сложно, поэтому nogil должен выпускаться в составе регулярных релизов и не обязательно он там должен быть по-умолчанию. 4. Это всё ещё не гарантированная история. Если что-то пойдет не так - от изменений откажутся. Развёртывание должно быть постепенным и наиболее плавным. 5. Выкатка будет происходить в 3 фазы, которые возможно изменятся: - В первой фазе nogil сделают возможным таргетом при сборке, чтобы разработчики могли тестировать свои пакеты. - Во второй фазе, когда изменения в API и ABI будут сформированы, а поддержка nogil от сообщества будет достаточной, nogil-сборку добавлят как "поддерживаемую, но не по умолчанию". - В третьей фазе nogil-сборку сделают сборкой "по-умолчанию", а от gil-сборки будут отказываться. 6. При успешной реализации nogil, ожидается падение производительности на 10-15% в худшем случае.
0
8
Недавно пришлось писать конвертор который транслировал Markdown в довольно специфичный формат. Была следующая идея - мне нужен парсер, который перегонит Markdown в синтаксическое дерево, которое я буду обходить. С обычным python-markdown в этом плане банально неудобно работать - у него нет простого и расширяемого API, который бы позволял решить мою задачу. А вот у mistletoe такое API есть. Например, вот так выглядит рендерер markdown в jira: class JiraRenderer(BaseRenderer): def render_strong(self, token): template = '*{}*' return template.format(self.render_inner(token)) def render_emphasis(self, token): template = '_{}_' return template.format(self.render_inner(token)) Ещё mistletoe можно использовать как утилиту. Например, вот так markdown-файл можно перевести в тот же формат Jira: mistletoe foo.md --renderer mistletoe.contrib.jira_renderer.JiraRenderer Поэтому, если вам нужна небольшая, но расширяемая библиотека для работы с markdown - берите её, не прогадаете. #библиотека
0
9
На второе октября намечен релиз Python 3.12, поэтому Никита Соболев (opensource разработчик и контрибьютор в сpython) рассказывает про новинки в новой версии и чуть затрагивает то, что ожидает нас в 3.13. Рекомендую посмотреть, чтобы оставаться в теме новых обновлений. #посмотреть
0
10
Помните, я рассказывал про такой фреимворк как Propan? В общем, программа Propan удаляется на смену Propan пришел FastStream, и весь новый функционал будет попадать в него. Первой моей реакцией было "што" и "зачем", ведь на первый взгляд может показаться, что поменялись только орга и название. Давайте разбираться. Во-первых, за фреимворком стоит не только сам Lancetnik, а целая команда из AirtAI, что является очень сильным усилением со стороны как разработки, так и поддержки. Второе, FastKafka переходит в такой же статус как и Propan. Всё по той же причине - новый функционал будут добавлять в FastStream. В свою очередь FastStream - это фреимворк, базированный на идеях FastKafka и Propan, который хочет взять от них самое лучшее и создать единый способ для написания сервисов, работающих с очередями. Третье, что показалось мне важным, разработчик Propan признаётся, что сделать унифицированный RPC для всех брокеров (например для Kafka) - задача сложная, особенно когда брокер by design плохо рассчитан на такую функциональность. Всё сводилось к тому, что тот самый простой высокоуровневый интерфейс плохо скрывал недостатки реализации, поэтому в FastStream от него отказались. Ещё генерацию темплейтов удалили, теперь проект можно генерировать при помощи cookiecutter. А что нового уже принёс FastStream? В первую очередь, мне понравился механизм фильтров. Ещё добавили кастомную сериализацию - по умолчанию FastStream работает с Json, но если у вас Protobuf, Avro или msgpack - больше никаких проблем нет, можно добавить собственную логику для сериализации. Отдельно хотел бы выделить систему мидлварей - теперь трассировку, логи, обогащение сообщений метаинформацией делать намного проще. Очень надеюсь, что проект будет развиваться семимильными шагами, ведь идеи FastKafka и Propan мне очень сильно понравились, а сам Propan я очень часто рекомендовал знакомым. #библиотека
0
11
Если вам приходилось работать с bash, например парсить логи, вы наверняка видели или использовали команды следующего вида: cat app.log | grep 'exception' | awk '{ print $2 }' Здесь мы последовательно считываем содержимое файла app.log, фильтруем по подстроке exception и выводим вторую колонку. Символ |, которая разделяет команды называется "пайпом" - он перенаправляет вывод из одной команды в другую, а вся эта конструкция в целом называется конвейером, и она очень часто используется в функциональном программировании. В Elixir есть оператор конвейера |> который позволяет передавать результат выполнения левого выражения в правое. Это позволяет делать вот такие штуки: 1..10 |> Enum.map(fn x -> x * 2 end) |> Enum.filter(fn x -> x > 10 end) [12, 14, 16, 18, 20] Здесь мы генерируем список от 1 до 10, умножаем каждый элемент на 2 и фильтруем только те, которые больше 10. Согласитесь, так удобнее работать с коллекциями, особенно там где данных много и их хочется как-то отфильтровать - нам больше не надо строить громоздкие циклы. Если вам интересно. как можно сделать такое в Python, то для вас есть библиотека Pipe. Реализация очень простая - библиотека добавляет класс Pipe который переопределяет оператор |. Далее мы оборачиваем наши функции в этот класс и можем строить конвейеры! Например, вот так мы можем получить сумму товаров, цена которых больше тысячи: from typing import NamedTuple from pipe import select, where class Product(NamedTuple): name: str price: int products = [Product("choco", 123), Product("auto", 10000), Product("photo", 1200)] sum( products | select(lambda product: product.price) | where(lambda x: x > 1000) ) # 11200 #библиотека
0
12
Недавно мой знакомый @nesclass (можете ему писать по теме доклада) выступал c докладом "Асинхронное варение MongoDB в Python" на Pytup. Автор объяснил наглядно в чем различие реляционных баз от документно-ориентированных, немного рассказал про подходы работы с БД, затронул тему object mapper'ов и много рассказал про Beanie - ODM для работы с MongoDB (про которую я писал) и саму монгу. Доклад отлично подойдет для тех, кто хочет ознакомиться с этим инструментом и послушать про подводные камни, с которыми часто встречаются новички.
0
13
Тианголо (создатель FastAPI) предложил новый PEP 727, который позволяет стандартизировать механизм документирования параметров. Причина проста - существует много псевдо-стандартов по форматированию параметров в docstring (например свои стандарты есть у numpy, гугла, много их!), но не все редакторы/IDE имеют возможность поддерживать эти "микроязыки". Он предлагает стандартизировать подход, используя существующий мощный инструмент в виде аннотаций типов. Основное предложение - добавление в typing новой функции doc, которая принимает единственный параметр documentation. Ожидается, что эта функция будет использоваться вместе с Annotated. А вот как это будет выглядеть: def create_user( lastname: Annotated[str, doc("The **last name** of the newly created user")], firstname: Annotated[str | None, doc("The user's **first name**")] = None, ) -> Annotated[User, doc("The created user after saving in the database")]: """ Create a new user in the system, it needs the database connection to be already initialized. """ pass Тианголо заранее позаботился и о старых версиях - так же предлагается добавить doc() в пакет typing_extensions, который используют старые версии питона для исключения проблем с совместимостью. Выглядит интересно, но важно понимать - автор пытается создать ещё один стандарт. Поддержит ли его комьюнити и уйдет ли PEP в работу? Остается только гадать. #pep
0
14
Немного девопсовский пост, так как на предыдущем месте работы я много админил линукса. Автоматизация - один из столпов работы любого админа, так как подготавливать сервера руками - занятие тяжелое и трудозатратное. Для этого я всегда выбирал Ansible - это довольно простой инструмент, который позволяет настраивать сервера из специальных yaml конфигов, которые называются плейбуками. Но какой бы вы инструмент не выбрали, рано или поздно конфигурация будет усложняться, а плейбуков/скриптов станет много. В какой-то момент всё это может сломаться, поэтому любую автоматизацию надо тестировать. Когда я админил, команда не хотела полностью завязываться на Ansible (соответственно Molecule отпадает), решено было искать инструмент, который позволял бы тестировать состояние сервера после работы любой автоматизации. И я нашел такой инструмент, имя ему - testinfra. Это плагин для pytest, который позволяет лаконично описывать тесты проверяющие состояние сервера. Например, мы написали автоматизацию, которая устанавливает nginx. Проверим, что он установлен: def test_nginx_is_installed(host): nginx = host.package("nginx") assert nginx.is_installed А теперь проверим, что сервис с ним запущен: def test_nginx_running_and_enabled(host): nginx = host.service("nginx") assert nginx.is_running assert nginx.is_enabled Самое важное - для него существует много connection backend'ов, которые позволяют подключаться к серверам для теста как по SSH (через paramiko), так и используя инвентарь Ansible. Так же есть бекенды для docker/podman/salt/kubectl/openshift/winrm/lxc - обо всём этом можно почитать здесь. Напоследок, вот вам еще кейс использования: одно время при помощи testinfra я тестировал правильность сборки контейнеров - все ли есть права, запустился ли сервис, в порядке ли конфиги и так далее. #devops
0
15
Занимаюсь в рамках петпроекта обработкой текста, появилась потребность проверять на каком языке написан текст. Сначала я попытался использовать langdetect, но он часто выдавал неправильные результаты. Как правило, плохие результаты выдавались по нескольким причинам: 1. Нет возможности ограничить языки, которые я хотел бы детектить. Мне надо определять всего четыре языка - украинский, русский, английский и немецкий. 2. Часто исследуемый мною текст слишком мал, из-за чего анализ ломался. По итогу я пошел искать другую библиотеку и нашел lingua, которая успешно справляется с проблемами langdetect. Важное отличие этой библиотеки от всех остальных в том, что она использует не только статистическую модель для определения языка, а ещё и механизмы, основанные на правилах - сначала определяется алфавит текста, ищутся символы которые уникальны для языка и после этого выбираются языки, на которых возможно написан текст. Но есть возможность улучшить этот процесс. Можно самому ограничить языки, на которых возможно будет написан текст, а это как раз то, что мне и нужно: from lingua import Language, LanguageDetectorBuilder languages = [Language.ENGLISH, Language.RUSSIAN, Language.GERMAN, Language.UKRAINIAN] detector = LanguageDetectorBuilder.from_languages(*languages).build() print(detector.detect_language_of("Hello from box with python!")) # Language.ENGLISH print(detector.detect_language_of("Привет от коробки с питоном!")) # Language.RUSSIAN Из-за ограничения языков вероятность совершить ошибку на небольших предложениях сокращается многократно. В добавок ко всему, ребята используют не только триграммы, которые очень часто используют для таких задач, а n-граммы от 1 до 5, из-за чего вероятность предсказания повышается. Причина такого решения проста - чем короче входной текст, тем меньше n-грамм доступно, а если мы будем проверять триграммами короткие заголовки - будут случаться ошибки. Ну и база - ограничение количества языков ускоряет работу и уменьшает потребление памяти, а при исследовании огромных текстов - это несомненный плюс. #nlp #библиотека
0
16
Появился PEP 723, который предлагает "встраивать" pyproject.toml в однофайловые скрипты. Предлагается добавить переменную __pyproject__, которая будет содержать в себе валидный TOML, описывающий метадату скрипта, в том числе как скрипт запускать и какие зависимости необходимы для запуска. К примеру, вот так будет выглядеть скрипт, которому для работы нужна библиотека requests и питон 3.11 или выше: __pyproject__ = """ [project] requires-python = ">=3.11" dependencies = [ "requests<3", ] """ import requests resp = requests.get("https://peps.python.org/api/peps.json") print(resp.json()) PEP прикольный, что-то такое есть в качестве экспериментального RFC в Rust. Из минусов хотел бы отметить то, что автоматическая установка зависимостей может привести к запуску нежелательного кода. Но решение банальное - перед тем как что-то запускать, проверяйте, что вы запускаете. #pep
0
17
GIL скорее всего уберут из Python! Руководящий совет объяснил статус PEP 703 (сделать GIL опциональным). Если кратко, то понятно следующее: — Они намерены принять PEP 703, но всё ещё работают над деталями, предстоит много работы. — Вероятно, лет через пять сборка без GIL будет ЕДИНСТВЕННЫЙ сборкой, так как они не хотят разделять комьюнити на no-GIL и GIL. — Совет не хочет повторения ситуации с Python 3, поэтому большое внимание будет уделено обратной совместимости. — Прежде чем отказаться от GIL, они внимательно будут изучать работу комьюнити в этом направлении. Ребята хотят убедиться, что переход будет плавным, а поддержка режима no-GIL будет достаточна. — Не смотря на все это, совет хочет иметь возможность "дать заднюю", если для комьюнити и языка это принесёт намного больше проблем, чем профита. Новость просто невероятная. Остается надеяться на комьюнити, будет ли оно готово адаптировать свои библиотеки под этот режим? #gil
0
18
Yoyo В текущих реалиях практически любой сервис использующий реляционную БД не может обойтись без миграций. Так уж сложилось, что в нашем питонячьем мире, в проектах почти всегда можно увидеть ORM (например SQLAlchemy) и пакет, который позволяет управлять миграциями, работающий с конкретной ORM (в случае с Алхимией это alembic). Но иногда попадаются такие проекты, в которых нам не нужна ORM, по разным причинам. В этом случае, для миграций можно использовать yoyo. Yoyo - это простой мигратор схем для нашей БД. Миграции здесь записываются в виде скриптов на SQL или на Python. Сгенерировать папку для миграций и конфиг можно вот так: yoyo init --database sqlite:///mydb.sqlite3 migrations А теперь создадим миграцию: yoyo new Опишем SQL для применения миграции (apply) и для её отката (rollback): from yoyo import step __depends__ = {} steps = [ step( "CREATE TABLE TEST (a int);", "DROP TABLE TEST" ) ] Теперь можно применить миграцию командой yoyo apply и после откатить её командой yoyo rollback. Внутри базы yoyo создает таблицу с логом всех операций (_yoyo_log), таблицу с применёнными миграциями (_yoyo_migration), а так же таблицу yoyo_lock который позволяет заблокировать миграции, которые будут идти с нескольких инстансов приложений. Вот такая вот простая и удобная библиотека :) Сайт | Sourcehut | PyPI #библиотека
0
19
Релиз FastAPI 0.100.0🔥 Себастьян закончил обновление pydantic-а. Теперь можно насладиться звуком ржавчины и приростом скорос
Релиз FastAPI 0.100.0🔥 Себастьян закончил обновление pydantic-а. Теперь можно насладиться звуком ржавчины и приростом скорости при переходе на новую версию FastAPI. Чейнжлог совсем небольшой получился https://fastapi.tiangolo.com/release-notes/#01000 p.s. в ближайшее время доберусь до чейнжлога pydantic v2 и сделаю обзорный пост
0
20
Релиз FastAPI 0.100.0🔥 Себастьян закончил обновление pydantic-а. Теперь можно насладиться звуком ржавчины и приростом скорос
Релиз FastAPI 0.100.0🔥 Себастьян закончил обновление pydantic-а. Теперь можно насладиться звуком ржавчины и приростом скорости при переходе на новую версию FastAPI. Чейнжлог совсем небольшой получился https://fastapi.tiangolo.com/release-notes/#01000 p.s. в ближайшее время доберусь до чейнжлога pydantic v2 и сделаю обзорный пост
0