Последние посты

Oh My Py
4 апр. 2023 г., 09:07
ChatGPT-бот: группы, внешние ссылки, шорткатыСделать GPT-бота легко, а вот удобного GPT-бота — намного сложнее. Последние недели я посвятил именно этому.Поэтому теперь pokitoki умеет вот что:— Работает не только в личных чатах, но и в группах. — Читает внешние ссылки (статьи, код, данные). — Поддерживает шорткаты (команды для нейросети). — Экономит время и действия в других частых сценариях.Код при этом старался сохранять понятным. Есть и комментарии, и тесты.Подробности на хабре: https://habr.com/ru/post/726692/
Oh My Py
11 мар. 2023 г., 11:39
ChatGPT-бот на PythonПоследние месяцы поставили рекорд по количеству программ, интегрированных с OpenAI. Я, конечно, тоже не смог остаться в стороне.В результате появился проект pokitoki — это чат-бот, который работает через официальное API OpenAI.Чем (на мой глубоко субъективный взгляд) он может вам пригодиться:— Демонстрирует, как писать несложных телеграм-ботов на питоне.— Демонстрирует, как интегрироваться с OpenAI.— Демонстрирует, как запускать питон-приложения в докере.— Сознательно сделан максимально простым, чтобы можно было быстро разобраться в коде.Ну и конечно, вы можете подключить его себе в телеграм (если сумеете зарегистрироваться в OpenAI).
Oh My Py
3 авг. 2022 г., 11:55изменён
JSON LinesНа днях узнал про формат JSON Lines. Это такой CSV на стероидах:— каждая запись идет отдельной строкой, как в CSV; — но при этом представляет собой полноценный JSON.Например:{ "id":11, "name":"Дарья" } { "id":12, "name":"Борис" } { "id":21, "name":"Елена" }Очень классная штука:— Подходит для объектов сложной структуры (в отличие от csv);— Легко потоково читать, не загружая файл целиком в память (в отличие от json);— Легко дописывать новые записи к существующему файлу (в отличие от json).
Oh My Py
18 июл. 2022 г., 07:47изменён
Попробуйте GoЧем больше я узнаю Python, тем больше мне нравится Go. Альберт ЭйнштейнНет, правда. Я нежно люблю питон, но кривая многозадачность и непонятное стремление авторов напихать в язык как можно больше новых фич — ощутимо раздражают.Попробуйте освоить Go в дополнение к Python, если у вас отзывается что-то из перечисленного:— Хотите поработать с компактным языком без фичеризма и горы легаси.— Посмотреть, как может выглядеть современная статическая типизация.— Писать код, который действительно работает быстро (без привычных для питонистов скидок из серии «а мне и так хорошо»).— Попробовать многозадачность здорового человека.— Деплоить докер-контейнеры размером в 10 Мб вместо 500 Мб.Я не думаю, что го обязательно заменит вам питон. Но что может стать отличным инструментом для некоторых задач — уверен.
Oh My Py
1 июн. 2022 г., 12:37изменён
Многозначительное многоточиеНе знаю, заметили вы или нет в посте о протоколах. Не самая известная штука:class Flyer: def fly(self): ...Это вполне рабочий код. В питоне ... (он же Ellipsis) — это реальный объект, который можно использовать в коде.Ellipsis — единственный экземпляр типа EllipsisType (аналогично тому, как None — единственный экземпляр типа NoneType):>>> ... is Ellipsis True >>> Ellipsis is ... TrueАвторы Python в основном используют ..., чтобы показать, что у типа, метода или функции отсутствует реализация — как в примере с fly().И в тайп-хинтах:
Oh My Py
31 мая 2022 г., 08:34изменён
Через протоколЦитата выше взята из PEP 544 (Python Enhancement Proposal, предложение о доработке), который был реализован в Python 3.8. Начиная с этой версии в питоне появились протоколы.Протокол описывает поведение без реализации (в других языках такие штуки обычно называют интерфейсами). Вот наш Летающий Объект:from typing import Protocolclass Flyer(Protocol): def fly(self): ...Мы используем протокол, чтобы указать, что объект должен обладать конкретным поведением. Наша функция умеет запускать только Летающие Объекты:def launch(thing: Flyer): thing.fly()Причем самим объектам не надо знать о протоколе. Достаточно обладать нужным поведением:class Frank:
Oh My Py
31 мая 2022 г., 08:22
Через базовый классЕсли расчехлить навыки программирования на джаве из 1990-х годов, получится небольшая иерархия:class Flyer: def fly(): ...class Frank(Flyer): # ...class Plane(Flyer): # ...class Superman(Flyer): # ...def launch(flyer: Flyer): flyer.fly()
Oh My Py
31 мая 2022 г., 08:12
Вариант «и так сойдёт» не требует дополнительных пояснений :–) А по остальным напишу отдельно.В комментарииЕсли вы привыкли избегать типов, то скорее всего обойдетесь именем переменной или комментарием к функции:def launch(flyer): """Launces a flyer (an object with a fly() method)""" flyer.fly()Почему бы и нет. Беда в том, что чем сложнее код, тем чаще сбоит «описательный» подход.
Oh My Py
30 мая 2022 г., 16:42

Oh My Py
30 мая 2022 г., 16:41изменён
Задачка: летающая свиньяДопустим, вы написали утилиту, которая отправляет что угодно в полет:def launch(thing): thing.fly()Ну то есть не прям все что угодно, а любую штуку с методом .fly(). Очень удобно: одной функцией запускаем и голубя Френка, и самолет, и даже Супермена:class Frank: def fly(self): print("💩")class Plane: def fly(self): print("Рейс задержан")class Superman: def fly(self): print("ε===(っ≧ω≦)っ")
Oh My Py
23 мая 2022 г., 15:12изменён
Великий РандомВсе знают про random.randint(a, b), который возвращает случайное число в указанном диапазоне:random.randint(10, 99) # 59Но модуль random предоставляет намного больше возможностей. Так много, что одной заметкой и не охватишь.Например, можно выбрать из диапазона с шагом:random.randrange(10, 99, 3) # 91Или случайный элемент последовательности:numbers = [7, 9, 13, 42, 64, 99] random.choice(numbers) # 42
Oh My Py
14 мая 2022 г., 12:30
Компактные (и не очень) объекты в Python




Oh My Py
13 мая 2022 г., 17:16изменён
Компактные объектыПитон — объектный язык. Это здорово и удобно, пока не придется создать 10 млн объектов в памяти, которые благополучно ее и съедят. Поговорим о том, как уменьшить аппетит.Допустим, есть у вас простенький объект «питомец» с атрибутами «имя» (строка) и «стоимость» (целое). Интуитивно кажется, что самое компактное предоставление — в виде кортежа:("Frank the Pigeon", 50000)Замерим, сколько займет в памяти один такой красавчик:def fields(): # генерит name длины 10 # и price до 100К # ... return (name, price)n = 10_000 pets = [fields() for _ in range(n)] size = round(asizeof(pets) / n) print(f"Pet size (tuple) = {size} bytes")
Oh My Py
11 мая 2022 г., 10:05изменён
Новости стандартной библиотекиКогда выходит очередная версия Python, все внимание достается новым фичам языка: моржовому оператору, слиянию словарей, паттерн-матчингу. Еще много пишут об изменениях в асинхронной работе (модуль asyncio) и типизации (модуль typing) — эти модули на виду и бурно развиваются.Остальным модулям стандартной библиотеки достается незаслуженно мало внимания. Хочу это исправить и рассказать, что интересного появилось в версиях 3.8–3.10.Планировал небольшую заметку, но не преуспел: получилась здоровенная статья. Старался выбрать только самое интересное, но все равно в обзор попали аж 17 модулей. Питон, он такой 😁Читайте на хабре: https://habr.com/ru/post/665020/P.S. Для каждого описанного новшества в статье есть ссылка на интерактивную песочницу (например, graphlib)! Спасибо Степику за нее ❤️
Oh My Py
9 мая 2022 г., 11:32
Как передать состояние в URL-параметрах




Oh My Py
9 мая 2022 г., 11:30изменён
Как передать состояние в URL-параметрахНа первый взгляд, передавать состояние в виде набора параметров URL легко и приятно.Строку или число — элементарно:{ "search": "potatoes", "page": 5 }→ ?search=potatoes&page=5Логическое значение — не сильно сложнее:{ "popular": true }→ popular=true popular=1
Oh My Py
8 мая 2022 г., 10:56изменён
Храним состояние в URLЕсли вы разрабатываете веб-приложение, то рано или поздно столкнетесь с проблемой сохранения текущего состояния системы для пользователя.Например, вы продаете через интернет элитный картофель. Покупатель заходит, настраивает фильтры поиска, видит список из 300 позиций.Переходит на третью страницу, открывает карточку картофелины и случайно нажимает на рефреш страницы. Как поступит ваше приложение?Я знаю такие варианты:— Не хранить состояние вообще — Хранить состояние локально — Хранить набор URL-параметров — Хранить сериализованное состояние — Гибридные подходыВот особенности каждого#код
Oh My Py
2 мая 2022 г., 16:08
Постраничный итератор для быстрой пакетной обработкиПредположим, вы считаете статистику по огромному датасету игрушек, проданных по всей стране за прошлый год:reader = fetch_toys() for item in reader: process_single(item)process_single() занимает 10 мс, так что 400 млн игрушек обработаются за 46 дней 😱В результате оживленного диалога вам удается убедить разработчиков, что так не очень быстро. На свет появляется функция process_batch(), которая обрабатывает 10000 игрушек за 1 сек. Это уже 11 часов на все игрушки, что значительно приятнее.Как бы теперь пройти по датасету пакетами по 10 тысяч записей? Тут и пригодится постраничный итератор!def paginate(iterable, page_size): page = [] for item in iterable: page.append(item) if len(page) == page_size: yield page
Oh My Py
27 апр. 2022 г., 12:45изменён
Считаем котов: итогиНекоторые выводы по многозадачности в питоне:— Даже если программа не использует многозадачность, удобно явно выделить акторов: читателя, обработчика и писателя. С ними код проще понять, модифицировать и повторно использовать.— Многозадачность через async — отличный легковесный и «родной» вариант для i/o-bound задач. Не забывайте только ограничивать количество одновременных задач.— Многозадачность через потоки подойдет для i/o-bound задач в легаси-коде, где нет поддержки async. Либо если хотите в перспективе переключиться на процессы с минимальными доработками.— Многозадачность через процессы подойдет для cpu-bound задач.Как справедливо отметили в комментариях, async вполне можно комбинировать с процессами. Но об этом как-нибудь в другой раз.#stdlib
Oh My Py
26 апр. 2022 г., 16:57
Считаем котов: процессыМногозадачность на async и потоках сработала, потому что наши акторы в основном ждут ответа от внешнего кластера. Python (в случае с async) или ОС (в случае с потоками) постоянно «жонглируют» обработчиками, а на CPU в каждый момент выполняется только один.Но что делать, если обработчикам нужно 100% времени CPU? Например, если они что-то вычислают, выполняют алгоритмы или работают со структурами данных? И потоки, и async здесь бессильны — от многозадачности не останется и следа.Единственный рабочий вариант с CPU-bound задачами — использовать честные процессы операционной системы. Благо на Python с процессами можно работать почти так же, как с потоками.Наши читатель (read_step), писатель (write_step) и обработчик (process_step) остаются прежними. Меняем пул потоков на пул процессов — и готово:filename = "data/urls.txt" manager = Manager() in_queue =
