-
Глава 8. Функции на языке Python
Главы
- Введение в документы
- Базовые возможности JSON
- JSON в таблицах
- Индексирование JSON
- Ограничения в документах
- Язык путей JSONPath
- Отчеты, функции, расписание
- Функции на языке Python
- Версионирование и архивация документов
- Релевантный поиск
Содержание
- Главы
- Предварительные шаги
- Простые функции на Python
- Сторонние пакеты
- Работа с json(b). Трансформации
- Функции для работы с заявками
- Прочие сведения
Обсудим тему, которая, надеемся, разожжет в читателе интерес: как подключить к Postgres другие языки, например Python? Техника предлагает интересные возможности, особенно для работы с документами. Читатель узнает, как связать интерпретатор Python с базой данных и что можно сделать с его помощью. Считайте эту главу факультативом к предыдущей – дополнением, которое оказалось слишком длинным для параграфа и публикуется отдельно.
В прошлой главе мы познакомились с основами функций. В числе прочего мы упомянули, что функции можно писать на разных языках. По умолчанию это SQL, который не отличается от обычных запросов. Диалект plpgsql предлагает переменные, циклы, исключения и все то, что свойственно императивным языкам.
-
Пароли в Unix pass
Расскажу, как я храню пароли.
Когда-то давно я, как и все, пользовался 1Password. В те времена это была казуальная программка, легкая и незаменимая. Я купил ее долларов за 50, когда она была версии 4 или 5, и счастливо ей пользовался.
Как это часто бывает, программа прошла зенит своего удобства. Фирма, которая ей занималась, возомнила себя центром мира по безопасности. Штат раздули, программа все больше усложнялась, фирма вышла на корпоративный рынок… В какой-то момент 1Password развернул облачную инфраструктуру и ввел подписку. Вдобавок программу переписали на электрон и Node.js, так что еще одним процессом Хрома стало больше.
Я начал искать замену, нагуглил различные Bitwarden и аналоги. Программы хорошие, не спорю. Но вышло так, что мне, как Раскольникову, захотелось “страданье на душу принять”. Другими словами, я выбрал самый сложный способ хранить пароли – утилиту Unix pass. Вообще-то программа называется просто pass, но к ней добавляют Unix, чтобы было понятно – та самая.
Программа pass – это попытка передать философию ранней эпохи Unix. Pass написана даже не Си, а на шелле. Это скрипт на шесть экранов, который ничего не делает сам, а только командует следующими утилитами:
- gpg для (де)шифрования файлов;
- git для истории хранения и репликации;
- редактором для ввода данных;
- pinentry для безопасной передачи пароля от GPG-ключа.
Просто же, да?
Хранилище паролей выглядит как обычный гит-репозиторий с деревом папок и файлов. Никакой жесткой структуры, все определят пользователь. Единица хранения – файл. В файле может быть что угодно, однако со временем устоялись следующие соглашения:
- первая строка файла содержит пароль;
- другие строки хранят пары поле-значение в качестве метаданных.
Пример файла с паролем:
1dAfs@#sh_t335 email: ivan@grishaev.me username: igrishaev url: https://some.site/loginКоманда
pass path/to/fileдешифрует этот файл и выплюнет в консоль. Командаpath path/to/file -cпрочитает первую строку (пароль) и поместит в буфер обмена.Pass generateсоздает случайный пароль с разными параметрами (длина, алфавит),pass editоткрывает редактор, чтобы изменить существующий файл и так далее. Командаpass git ...совершает любое действие с репозиторием; чаще всего понадобитсяpushиpull. Коммиты на каждое действие программа создает сама.На маке вместо
pinentryпонадобитсяpinentry-mac– порт этой утилиты под яблочные устройства. Пропишите к ней путь в этом файлике:# ~/.gnupg/gpg-agent.conf pinentry-program /opt/homebrew/bin/pinentry-macЧтобы хранить все это добро, вам понадобится две пары ключей. Первая пара – публичный и закрытый ключи GPG. Вторая пара – SSH для репозитория. Дополнительно каждый приватный ключ должен быть зашифрован кодовым словом.
Все эти ключи следует распечатать на бумаге и хранить в разных местах: на работе, дома, у бабушки в деревне. Кодовые слова – в голове.
Поскольку unix pass – консольная утилита, для нее написана тьма графических оберток. Как и сам pass, они ужасны: поделки на C++, Tcl/Tk и прочее. В том числе есть плагины для Емакса и Вима. Попробовав пару оберток, я принял верное решение – предпочел консольную версию. Ее вполне достаточно.
Для Андроида написано несколько программ, для айфона – одна, которой я и пользуюсь. Обновляется она примерно раз в пять лет; топорная, местами странная, но работает. Первичная настройка тяжела: нужно перетащить GPG- и SSH-ключи на телефон, а они, как вы помните, занимают лист А4. В идеале вы копируете ключ на яблочном ноуте и телефон подхватывает буфер обмена — конечно, при соблюдении десятка условий.
Серьезный недостаток приложения в том, что оно не умеет решать конфликты Git. Если вы поправили файл одновременно на компе и телефоне, то при синхронизации программа скажет “конфликт”, и все – даже нет кнопки “принять своё” или “принять чужое”. Решается повторным скачиванием всего репозитория.
Вы, наверное, хотите знать, как я перенес пароли из 1Password в pass? В интернете полно Питон-скриптов, которые обходят экспорт 1Password и вставляют куда надо. Но сказано же: “страданье принять”. Я все сделал вручную. Примерно год я жил в режиме hit or miss: когда нужен был пароль, искал его в pass, а если не находил, переносил руками из 1Password. Со временем все нужное переехало в pass, а в старой системе остался хлам, который мне не нужен. У меня и сейчас установлен 1Password со старой базой, но я не открывал его уже много лет.
В этой статье я не буду описывать все детали установки. Предлагаю вам замечательный сайт-одностраничник, посвященный программе. Также есть достойная статья на Хабре “Знакомьтесь, pass”, где все подробно описано (но к некоторым вещам я пришел сам). Если у вас будут вопросы, задавайте: я отвечу и дополню заметку.
-
Экран маков
Я сменил несколько макбуков, и у всех одна и та же беда: на экране отпечатывается клавиатура. Поначалу это выглядит невинно: видны только уголки, но затем они собираются в квадратики. Если не принять мер, со временем отпечатывается контур тачпада.
Пишут, что отпечатки можно оттереть, но это не так. Часть следов пропадает, однако затем кнопки физически повреждают экран. Можно тереть следы до дыр – они никуда не денутся.



Я сменил три макбука, плюс параллельно пользуюсь корпоративным. Заметил, что чем раньше модель, тем устойчивей она к отпечаткам. Например, на ноуте 2014 года они появились чуть ли не через три года; на ноуте 2020 года – через два, на ноуте 2025 года – через несколько месяцев.
Почему это так, понять нетрудно. Ноутбуки стараются ужать, и расстояние между экраном и клавишами становится меньше. Я не измерял, но по ощущениям оно меньше миллиметра. Достаточно надавить пальцем, чтобы экран коснулся клавиш. Что уж говорить о переносе ноута в рюкзаке, когда на него давят другие вещи.
На корпоративный ноут я боюсь дышать и за все время носил его в рюкзаке раз десять. Однако и на нем уже появился нестираемый дефект. Ну а самая жесть – это нанотекстура.
Напомню, что в последний раз я брал ноут с нанотекстурой. Мне нравится матовый экран и тот факт, что видишь картинку вместо своего отражения. Однако такой экран очень нежный, любой тык пальцем заметен сильнее. Как следствие, он уязвим для отпечатков клавиш. Не прошло и нескольких месяцев, как на экране появились контуры кнопок и тачпада. Это именно физические повреждения, и никакие салфетки-тряпочки не помогут.
Насколько я понял, единственный способ избежать порчи экрана – это подкладывать что-то между ним и клавиатурой, когда ноут закрыт. Вопрос – что именно? В интернете советуют резиновую накладку или тряпочку, но на мой взгляд это опасно: то и другое толстые, а расстояние между экраном и кнопками – доля миллиметра.
Помните, когда в первый раз открываешь ноут, в нем постелена хрустящая тонкая бумага? Это и есть верное решение. Разумеется, та бумага сразу идет на помойку, и только потом понимаешь, что она не просто так. Поэтому берем обычный лист А4 и кладем в ноут. Делаю так уже какое-то время и заметил, что помогает: экран чище, следы перестали разрастаться.
Как правильно заметили на Reddit, по-хорошему надо подать на Эпл в суд. Пусть ноут будет толще на пару миллиметров, зато не испортится экран и не придется ходить с прокладкой. И я ни за что не поверю, что в самом Эпле не в курсе проблемы.
-
Just Learn SQL
Через третьи руки я получил интересную ссылку: What ORMs have taught me: just learn SQL. Статья интересная и в целом повторяет все то, о чем я говорил у себя в блоге. ORM – это игра, в которую невозможно выиграть. Она завязана на том противоречии, что в ORM продвинутые средства SQL недоступны. А если пользоваться только доступными средствами, то либо их не хватает, либо возникает лишний код в приложении.
Хотя все это очевидно, находятся те, кто не верят. Однако не обязательно верить мне или автору – можно обратиться к нейтральным источникам, которым не свойственны подтасовки.
Напомню, в Кложе есть два подхода для работы с SQL. Первый – библиотека Hugsql с очень простым принципом. Вы пишете сырой SQL, который позже становится функцией. В эту функцию передают подключение и параметры, а внутри выполняется тот SQL, что вы написали. Он может быть сколь угодно сложным и относиться к какому угодно диалекту: библиотека просто передает его драйверу и возвращает результат.
Второй вариант – библиотека HoneySQL для построения SQL из данных. Это еще не ORM, но уже шаг в данном направлении. Например, передаешь в библиотеку словарь с вектором векторов словарей и получается SQL. Болванку запроса легко строить по условиям или на базе каких-то других данных.
Так вот, интересен следующий факт. В библиотеке Hugsql последний коммит был два года назад и касался документации. Всего коммитов около 200. В отношении кода изменения были четыре-пять лет назад. Активных фаз у проекта всего две: в 2016 и 2022 годах, при этом число коммитов в это время измеряется десятками.

С HoneySQL ситуация другая: коммиты и релизы выходят постоянно. Всего коммитов около 1400. Шон Корфилд (автор проекта) уже давно развивает HoneySQL, при этом динамика проекта противоположная: коммиты и релизы выходят все чаще. В Слаке регулярно приходит народ и просит добавить ту или иную фичу какого-то диалекта: хитрую агрегацию этой базы, приведение типа другой базы и так далее.

Доходит до того, что один диалект ворует возможности другого. Например, я использовал недокументированные возможности HoneySQL, чтобы строить JSON Path в Postgres, например, что-то вроде
where doc @@ '$.path.to.attribute == "some-value" 'В одном из релизов все отвалилось. Оказалось, к Шону пришел какой-то тип и сказал: давай сделаем пути JSON для SnowflakeDB. В этой самой Snowflake другие кавычки и разделители, которые не дружат с Postgres. Мои решения превратились в тыкву, и пришлось экстренно исправлять.
К чему это все: выразить SQL на языке, отличном от SQL, в целом невозможно. Проект HoneySQL это подтверждает: даже не смотря на активную разработку, найдутся такие потребности, которые нельзя выразить списком словарей – а если и можно, то это долго и непонятно. У библиотеки Hugsql такой проблемы нет: пиши что считаешь нужным, она только передает запрос драйверу – то самое “just learn SQL” из заголовка статьи.
Конечно, для удобной работы нужны оба средства, однако важно понимать приоритеты. Чтобы выразить SQL в виде чего-то – ORM или DSL – нужно понимать SQL. При этом часто оказывается, что знания первого достаточно.
-
Эмпатия
Уже писал: у ребят, подсевших на AI, со временем пропадает всякая эмпатия. Можете спорить, доказывать обратное, но я вижу все больше этому подтверждений.
Например, есть внутренняя система, которая уведомляет об ошибках. Сообщение об ошибке выглядит примерно так: “что-то сломалось”. Никаких деталей, стектрейса, вообще ничего, за что можно зацепиться. Смотрю исходник – все эти данные есть, нужно только их показать.
Спрашиваю: ребят, ну вот получили вы фразу “что-то сломалось”. Какие ваши действия? Ответ просто убил. Они копируют ее в форму на внутреннем сайте, а там агент или какая-то модель, я не разбираюсь. Агент сканирует те самые логи, которые были под рукой у скрипта, и пишет, в чем ошибка.
Потрясающе, да? Все данные в контексте, но мы их не покажем. Сходи к агенту, и он криво-косо вытащит те же логи, что были у нас.
Никто не видит проблемы. Оказывается, поправить питон-скрипт сложнее, чем дергать агента, жечь токены и тупить в монитор.
Буквально в тот же день аналогичная проблема: плохо сделанная работа, ничего не понятно. Спрашиваю: как с этим работать? Разработчик шарит экран и показывает: вот у меня тут Клод, здесь такой агент, сякой агент и три плагина в редакторе. Вбиваю сообщение об ошибке, и агенты мне все подсказывают.
Рад за тебя! Но беда в том, что не у всех такой сетап. У меня лично нет клодов-агентов. Неужели в голову не пришла мысль, что нужно сделать удобно всем, а на расчитывать, что каждый полезет в AI?
И такого становится все больше: зачем делать работу хорошо, если всегда есть AI?
Подсевший на AI разработчик напоминает хорька в норе: главное, чтобы мне было удобно, а остальное неважно. Иногда от подобных ответов накатывает такое отчаяние, что хочется кататься по полу – а собеседник даже не понимает, что происходит. Ну и что, что соощение непонятно? Можно ведь спросить у агента, так что какая разница?
Это обескураживает.
-
Куда впадает Волга?
Когда меня спрашивают, куда впадает Волга, я спрашиваю в ответ: куда впадает Янцзы? Начинается кудахтанье и хлопанье крыльями, мол, не наша река. А что значит “не наша”? Расстояние на глобусе между Волгой и Янцзы — пятнадцать сантиметров. Не вижу причины, по которой нельзя его чуть-чуть повернуть. Или что: “наши” реки учить надо, а “чужие” не надо? Странная логика: в географии таких терминов нет.
Разницы между Волгой и Янцзы я не вижу. Есть и другие реки, и все они куда-то впадают. Незнание отдельной реки ни о чем не говорит.
Чтобы вам не гуглить: Янцзы впадает в Южное китайское море. Я узнал это случайно из туристического справочника, когда ездил в Китай. Просто запомнилось.
-
Самокаты
Напомните, откуда взялось мнение, что можно встать на самокат и поехать куда хочешь? Ничего, что прокатный самокат весит под 20 килограммов, а человек на нем — в среднем 60? Суммарная масса 80 кг разгоняется до 20-30 км в час, что опасно для всех: и самокатчика, и тех, кто рядом.
Самокату, как и любому транспорту, нужна инфраструктура. Поезжай по велодорожке или ступай в особое место в парке, где тусуются самокатчики. Нет велодорожек? Увы, ты пролетаешь. Пиши в управу, голосуй на госуслугах и так далее. Но почему надо ездить по тротуару? Это место для пешеходов. Не решайте свои проблемы за счет других.
То, что самокатчики сбивают друг друга как кегли, меня не волнует. Может быть, потеряв несколько зубов, они поймут, что не нужно опережать поток движения в три раза. Но они очень опасны для детей. Скажем, идет ребенок, а сзади его обгоняет самокатчик. Ребенок увидел бабочку, рванулся вбок — и чуть не попал под 80 кило на огромной скорости.
Та же самая ситуация с доставщиками. Как-то раз я подслушал их разговор, и тезисы примерно следующие. Если ездить по проезжей части, нужно соблюдать ПДД для легких мотоциклов (самый правый ряд и правая сторона). Соблюдая правила, курьер не успеет доставить заказ. Вдобавок менты устраивают засады, штрафуют, задерживают под разными предлогами, чтобы добиться взятки. Поэтому проще ездить по тротуарам.
Вот и получается, что обеим сторонам — доставщикам и ментам — удобней, когда курьеров выдавливают с дороги на тротуар. Это проще, чем действительно следить за безопасностью. В оправдание курьеров можно сказать, что по тротуарам он стали ездить очень медленно. Хватило всего пары случаев самосуда, чтобы курьеры все поняли.
Любой электротранспорт на тротуаре можно обозначить так: решение личных проблем за счет других. Нет велодорожек? Ничего, поеду между детьми. Не успеваю доставить заказ? Ничего, срежу через парк. Причины в каждом случае одинаковы: нет инфраструктуры, нет желания ее развивать, личиное безразличие к окружающим и ноль эмпатии.
-
О материализации
Когда говорят о кэшировании, для меня это тревожный знак. Да, я понимаю, что порой оно необходимо. Однако у меня возникает вопрос: понимает ли тот, кто говорит о кэшировании, весь набор проблем, что оно несет?
Напомню, что проблем с кэшем довольно много. Когда-то его нужно сбрасывать, когда-то — прогревать. Кэш должен быть транзакционным: если кто-то взялся его обновлять, другие клиенты должны ждать. Сюда же — проблема сериализации и походы в сеть.
Вместо сериализации я предпочитаю материализацию. Термин я взял из Постгреса, но его можно применить и к другим системам.
В Постгресе материализация работает так. Предположим, есть тяжелый запрос: много джоинов и сложных условий. Из него делают мат-вьюху и сбрасывают ее в таблицу по расписанию. Выборка из готовой таблицы быстрее на порядки. Важно, что эта таблица доступна всегда. Даже если мы не обновим вьюху, то все равно получим данные. Обновление вешают на крон или событие.
Другой пример: есть апишка, которая возвращает список отделений фирмы. Отделения появляются редко, поэтому ходить за ними в базу нет смысла. Проще выгрузить отделения в json-файл и раздавать его Nginx-ом. Задача выгрузки тоже ставится на крон.
Еще пример материализации — мой блог. Он устроен на Jekyll — генераторе статичных сайтов. При запуске Jekyll обходит md-файлы и производи файлы html. Далее они раздаются как статика; нет обращения к базе, Редису или очереди задач. Задачу обновления сайта — или материализации — обычно ставят на гит-хук или Github action, но я запускаю ее вручную. Таким образом собранный сайт есть всегда, пусть и с отставанием.
И еще пример: скажем, есть у вас в фирме тормозная CRM. Ее апишка держит не более полутора запросов в секунду и огорчает всех клиентов. Тут же находится обезьянка, которая предлагает Редис. А решение простое: реплицировать базу данных CRM в другую базу (частично или полностью). В реплицированной базе завести мат-вьюхи, которые собирают нужные проекции; вьюхи обновляются по крону. Даже если CRM отвалится, у вас будет копия базы, и что-то вы покажете. Может быть, данные будут не самые свежие, но это лучше, чем вечный спиннер или “попробуйте еще раз”.
Идея материализации в том, что данные есть всегда, и показать их очень легко. В идеале — прочитать файл или плоскую таблицу. Нет такого, что данные собираются по трем микросервисам, а потом еще обрабатываются. Наоборот — все готово, нужно только показать.
И есть фоновая задача, которая готовит данные: лезет в сервисы, очереди и другие малоприятные места. Эта задача отвечает за то, чтобы данные были актуальны. Если она отвалится, мы покажем устаревшие данные, что почти всегда лучше, чем свалиться с ошибкой.
Не всегда материализация полезна; возможно, она не решит какие-то из ваших задач. Но лично я рассматриваю ее как более разумный шаг по сравнению с кэшированием. Иногда материализация оказывается очень и очень в тему.
-
Сайты образовательных заведений
Поговорим о явлении под названием “сайты образовательных заведений”. Не знаю, обращали вы внимание или нет, но эти сайты довольно меметичны и представляют вещь в себе. Каждый раз, посещая их, я закусываю щеку, чтобы не рассмеяться.
Итак, сайты учебных заведений строятся по одному и тому же паттерну. Прежде всего это главная страница, за которой более-менее следят. На ней все современное: контент появляется из пустоты, верстка идет этажами (слоями), везде карточки с фотографиями из фотостоков. В большинстве случаев используется Реакт, а не jQuery. Видно, что работу поручили грамотному, современному фронтендеру.
Следует, однако, понимать, что эта страница — ширма, прикрывающая срам. Стоит кликнуть на сайт кафедры или факультета, как вы улетите на поддомен. Там крутится ублюдочная CMS на PHP вроде Вордпресса или Джумлы. Ее мажорная версия отстает на пять-шесть единиц. Возникает ощущение, что вернулся в нулевые. Макет делится строго на шапку, контент и сайдбар. В сайдбаре — опрос “Как вам новая версия сайта?” (новая, блин). Поиск не работает и выдает заглушку Апача, потому что не установлен модуль.
Содержимое не уступает технической части. Все данные устарели; актуальные данные выкладывают в виде сканов. Прочитайте это предложение еще раз: данные выкладывают в виде сканов. С подписью ректора, между прочим! Официально заапрувленный контент. Чтобы найти расписание занятий или учебную программу, нужно скачать скан на 10 мегабайт, сделанный на убитом железе. Далее просмотреть десять страниц, чтобы найти нужную информацию.
На сайте нет ни одной формы. Чтобы отправить заявление, качаешь вордовский файл, заполняешь и шлешь на почту. Имя файла примерно такое:
zajavka_na_dopolnitelnye_kursi_2026_(2)_final.docx.rarПосле скачивания пять минут тратишь на то, чтобы распаковать rar.
Заведует сайтом админ Валера, который то в отпуске, то на пересдаче сессии, то в пьяном загуле. Сайт может лежать месяцами, прежде чем это вообще заметят.
Посещая сайты университетов, я обращаю внимание не на главную, а на поддомены факультетов. Именно их состояние говорит о том, насколько в заведении следят за бардаком. Главная страница, где фрондендер подключил Реакт, увы, не отвечает на этот вопрос — ровно как ни на один другой.
-
AirPods Pro 3
Недавно купил уши AirPods Pro 3. Было бы странно писать на них обзор, потому что в сети их тысячи. Ограничусь лишь одним фактом.
В ушах классное шумоподавление, и покупать их следует только их-за этого. Ощущения трудно передать словами: надел — и словно провалился в другой мир. Не слышно кипящего чайника и льющейся воды. Совершенно пропадает шум машин с улицы. Испытал в поезде и даже самолете, и это просто поразительно: гул самолета становится едва слышным, словно жужжание насекомого.
Поэтому покупку я рассматриваю только с позиции подавления шума. AirPods — это такие электронные беруши, которые полностью устраняют шум. Подойдет тем, кто не любит громких звуков и предпочитает тишину.
Пару раз я даже спал в них, и это был замечательно. Разве что девайс великоват, так что со временем я откатился на обычные затычки.
Может быть, это личное, но я не люблю громких звуков: когда кто-то громко говорит или музыка играет выше адекватного уровня. Особенно этим страдают бары: зашел — а тем ревет магнитофон. Как мне разговаривать с друзьями? Склоняться через весь стол и кричать в ухо? Спасибо, мне такого отдыха не нужно.
Другой случай — каток. Зимой мы всей семьей ездим на крытый каток и катаемся по часу. Одна беда — иногда попадаем на “диджей-сеанс”. Это когда какой-то уродец врубает музыку так громко, что раскалывается голова. В таких случаях я ношу с собой затычки, а вот теперь мне помогут уши.
Испытать это чувство — погружение в полную тишину — я бы посоветовал каждому. Оно напоминает, как редко вокруг нас бывает беззвучие. Знаете выражение — звенящая тишина? Оно происходит из того факта, что мы постоянно что-то слышим, и когда звуки пропадают, мозг начинает судорожно их улавливать. С AirPods привыкаешь к тому, что абсолютная тишина — это нормально.
Само собой, не следует носить их за рулем и при ходьбе по улице: повышается риск несчастного случая. Надевайте их только за рабочим местом.
С подключением по блютузу все по-прежнему: полная задница. Если достать уши, и рядом несколько яблочных устройств, они станут подключаться к каждому и прерывать звук. Все это без какой-либо системы и понимания. Чтобы не трепать родственникам нервы, отключил на их устройствах блютуз.
Но повторюсь, подавление шума — это нечто, по крайней мере для меня. Удивительное открытие.