Нервный программист
123 subscribers
53 photos
1 video
1 file
30 links
Эмоционально об айти и программировании
Download Telegram
Я капец как не люблю и не умею рисовать. Каждый раз, когда мне надо что-то где-то изобразить, у меня происходит вспотевание лба и других частей тела. Даже если я использую что-то вроде draw.io, где уже есть куча готовых элементов - перетаскивай и используй - у меня всегда выходит какой-то разноцветный кал 🌈

Поэтому я все больше проникаюсь декларативным рисованием диаграмм. В частности, мне очень зашел mermaid🧜‍♀️

Под "декларативным рисованием" я подразумеваю работу с диаграммами с помощью специального конфигурационного файла. Непосредственная отрисовка диаграмм отводится ПО, которое принимает на вход этот файл, а на выходе получается уже готовая картинка. Любые изменения в существующей диаграмме делаются через модицикацию конфига.

Именно так и работает mermaid. Отрисовка диаграммы выполняется в контексте определенной нотации, например Flowchart, Entity Relationship, Gantt и др. Mermaid поддерживает более 20 различных нотаций. Для каждой нотации существует свой описательный язык.

Очевидные плюсы такого подхода, по сравнению с традиционными рисовалками в стиле "драг-н-дроп прямоугольник":
* стандартизованность - единое представление одних тех же типов элементов
* diagram as code с возможностью положить диаграмму в vcs и отслеживать историю изменений
* local first approach (привет obsidian и его клоны)

Но существует также и неочевидный плюс. Подобный подход позволяет думать, рисуя. Потому что я не отвлекаюсь на построение лэйаута для элементов, выравание их, покраску, выбор размера шрифта и прочие очень важные действия. Все эти проблемы уже решили за меня. Вместо этого я могу сконцентрироваться на сути диаграммы, на абстрактном отношении между ее элементами. А ее визуальное представление помогает мне понять, чего не хватает или что здесь лишнее. При таком подходе диаграмма выступает одним из инструментов проектирования.

Подобное можно испытать не только в mermaid. Например, существует C4 нотация для построения диаграммы архитектуры ПО. Чаще всего C4 используется для документации уже существующей архитектуры. Однако недавно мне довелось заниматься проектированием системы с нуля (в рамках обучающего курса, ничего серьезного). Я использовал PlantUML для построения С4 диаграммы этой системы. И в какой-то момент, поймал себя на мысли, что я проектирую с использованием этой диаграммы, используя PlantUML в качестве языка проектирования. Очень круто!

А какие же минусы такого подхода? Главный и наверное единственный минус - нужно разобраться в нотации и в описательном языке выбранного инструмента. Это потребует от вас какое-то время на вкатывание. Но благо, в том же memaid документация строится на конкретных примерах. Так что пара часов максимум - и вы уже шарите в этой теме.

Но даже в этом минусе я вижу плюс. Вам надо будет изучить нотацию выбранного типа диаграммы, а значит, у вас будет правильное понимание примитивов данной нотации, вы не изобразите нестандартизованную херню.

В общем, если вы часто чего-то рисуете с помощью перетаскивания стрелочек, то я рекомендую попробовать посмотреть в сторону mermaid и подобного тулинга. Если вы редко рисуете, то тут уже на ваше усмотрение. В таком случае проще может быть накидать что-то драг-н-дропом, чем разбираться в документации.

В комментах поделитесь, где вы рисуете ваши диаграммы?
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
6🦄1
Если же говорить о не декларативных рисовалках, то приятным открытием прошлого года стал Excalidraw. Это тот редкий случай, когда простота и "красивость" выделяет продукт среди конкурентов. Вы только посмотрите на стиль получающихся картинок! Это супер мило😍

В excalidraw очень "примитивная" стандартная библиотека примитивов, что также является плюсом по мне. Но если хотите, можно скачать кучу готовых специализированных библиотек.

Из недостатков: это local first тулза. Синхронизация и колаборация доступны только в платной версии. Приходится ставить расширение для хрома, чтобы манагерить свои рисунки.

Но эти минусы почему-то не отпугивают пользователей. 90к звезд на гитхабе говорят сами за себя ⭐️

Кстати, на собесах по системному дизайну часто используют именно excalidraw. И мне кажется, что причина в его простоте. Люди без проблем разбираются, как им пользоваться в процессе.
4🔥1
На работе уважаемые разработчики из индии за 3 недели накидали прототип микросервиса с использованием python фреймворка FastAPI. Моя задача теперь выкинуть весь код к хуям довести прототип до ума. Решил подойти к задаче, как профи. Поэтому потратил неделю на изучение этого вашего питона и FastAPI. И знаете, это капец сложно! Ниже поясняю за базар.

Немного вводных данных. FastAPI - фреймворк, который построен на асинхронном питоне (asyncio), т.е. мы везде имеем наши любимые async - await. Вроде после js проблем быть не должно. FastAPI имеет очень подробную документацию. Она будто для дебилов написана и затрагивает не только сам фреймворк, но даже разработку на python в целом.

Но FastAPI начал меня страпонить практически сразу. Сначала я решил познакомиться с миграцией баз данных. В документации меня ждала лишь ссылка на библиотеку alembic. Сама по себе библиотека потная и душная. Самые душные миграции в моей жизни. Однако при тестировании все миграции применялись к public схеме в постгресе. И я никак не мог понять, а как блэт поменять схему-то. Благо, я оказался такой не один, и ребята тем же вопросом задались. Еще и оказалось, что с асинхронным драйвером там свои танцы с бубнами. Пиздец 🤡

Далее, как передать database connection во все хэндлеры запросов? Я слышал, что в FastAPi есть DI. Решил познакомиться с ним поближе. Он странный. Но в доке написано "This is very useful when you need to... Share database connections". "Отлично! А как? Как мне создать пулл коннекшнов при старте приложения, а потом использовать их везде?" Нет ответа в доке! А люди-то тоже интересуются в интернете, например тут и тут. Ребята из индии на каждый запрос к бд коннектятся от безысходности😔

Тоже самое про MQ. Захотел при старте приложения подконнектиться к Rabbit MQ и слушать, че там происходит. Вроде разобрался, как при старте FastAPI коннекшн сделать. Вопрос, где его хранить, ведь он потом еще понадобится для отправки сообщений? Ну положил в глобальную переменную, штош 🤡 Кстати, у драйвера aio-pika для Rabbit MQ периодически отваливается коннекшн без реконнекта или эксепшна. Приложение тихонько перестает слушать, че там у вас в очереди происходит. Пока хз, че с этим делать. Будем смотреть.

Лан, давайте про сам питон. Стоит ли говорить, что большая часть всего, что есть в интернете по питону - это про синхронный питон. Ансинхронщина же будто припиздрячена костылями к этому самому синхронному питону. Изза этого часто непонятно, а какую библиотеку выбрать. Например, есть мегапопулярный адаптер для постгреса psycopg. Но он изначально был без поддержки asyncio. Но щас вроде завезли в 3й версии. Но почему-то все советуют asyncpg. Тоже самое с клиентом для RabbitMQ, потому что есть синхронный pika (но с asyncio коннектором), а есть aio-pika.

Если хочешь в бэкграунде че-то поделать с помощью asyncio.create_task, то обязательно надо сохранить куда-то сам task, потому что, если этого не сделать, то сборщик мусора может эту корутину удалить. Так в доке написано. Я прям охерел с этой прикормки 😳 Самое прикольное, что в инете все примеры че то забивают на это. Хз, что делать, на всякий случай в глобальную переменную все сохранил. Люблю глобальные переменные 😊

Кстати, захотел эту переменную с тасками типизировать, ну типа указать, что у меня тут коллекция Taskи хранит. Так и не понял как это сделать! Где типы для asyncio?

IDE помогает слабо. Куча библиотек написана без типов.

context manager (ну это который with pampam() as huita) проглатывает исключения 😳 я так понимаю, это зависит от реализации конкретного менеджера. но все же, для меня это не совсем ожидаемое поведение. Неожиданно и то, что исключения тупо пропадают в корутине, которая task в бэкграунде.

logger из коробки не работал че-то у меня. Ну вот ребята со стэкоферфлоу помогли.

Вообщем, может создаться впечатление, что я тут жалуюсь. Но это не совсем так. Это я свой опыт пытаюсь переложить на незнакомый инструмент. И он ложится неидеально, это нормально. Надо подпривыкнуть 😊 Надеюсь, получится освоить этот популярный язык, и наконец-то по-настоящему войти в айти!💪
3🤔1🤯1🤡1🏆1
Жиза?
😁9👍3💯21
Помню, в далеких 2010х годах, когда я еще занимался подготовкой людей, одним из важных навыков для программиста считалось "умение гуглить". Без этого базового умения было очень тяжело учиться программировать. Поэтому, если у кого-то намечался пробел в этом навыке, необходимо было это как можно быстрее исправить.

Сейчас есть такое ощущение, будто у меня самого образовался пробел с этим. Во всяком случае, найти что-либо полезное в гугле стало значительно труднее.

Как вы помните, я старательно стараюсь вкатиться в айти, как питон разработчик. Поэтому приходится очень много гуглить. И как же это тяжко большинстве случаев!😔

Ну вот вам пример из последнего: запрос "aioboto3 get s3 file content type" в гугле не возвращает нихера! Это конкретный запрос, который должен приводить к ответу про вызов метода "head_object" у s3 клиента в библиотеке aioboto3. DeepSeek отвечает на раз, да еще и с примером кода.

Часто, когда мне надо что-то найти по программированию, я добавляю "reddit" к поисковой строке, потому что на реддите очень много крутой инфы, но гугл этого почему-то не видит, поэтому надо ему помогать. Либо при аналогичных запросах без "reddit" (например, про "топ чего то там...") будет выдавать мусорный и/или проплаченный контент.

На мой субъективный взгляд, качество поисковой выдачи гугла по технической тематике существенно снизилось😢 Гугл все еще неплохо справляется с запросами про конкретные ошибки или исключения. Но если мне нужно спросить про какую-то базу, то я скорее пойду в chatGPT или DeepSeek. Например, недавно я хотел изучить contextvars в python. Гугл уверенно отправляет на официальную документацию, которая, на мой взгляд, не очень удачная. По ней даже непонятно толком, зачем нужны эти contextvars. DeepSeek же вообще красавчик, все раскидал, с примерами, с чувством, с расстановкой. Если же вы хотите узнать про еще более классическую базу (например, how tcp connection established), то это сразу LLM, гугл будет тратой времени.

Пока что гугл остается местом номер 1, куда я иду за инфой, но как-будто это скоро может поменяться.

Делитесь, есть ли у вас ощущения, что гугл скатился, или я один такой? Может быть будущее за специализированными поисковиками или LLM?
4
Найдите себя. Я вот чечик из нижнего левого угла🫠
🤣63
Если судить по вашим вялым реакциям на мои околотехнические посты, то либо вы устали от этих лонгридов, либо я исписался😔 Будем надеяться на второй вариант, поэтому сегодня разгрузочный пост. Будем говорить про время.

Знаете, я не очень люблю чистить зубы. Не в том плане, что я их не чищу. Просто, это очень скучное занятие. И если кто-то скажет "я каждый день с нетерпением жду утра и вечера, чтоб можно было до блеска надраить свои клыки", то я буду с осторожностью относиться к такому человеку 🤨

Недавно у меня появилась электрическая зубная щетка. Она работает по таймеру. Подразумевается чистка каждого из 4х сегментов пасти по 30 секунд. Итого, весь сеанс чистки зубов занимает 2 минуты. Получается, я провожу по 2 минуты утром и вечером каждый день наедине с этим вибрирующим устройством😏

В один из таких прекрасных моментов я подумал, а сколько я трачу времени в год на чистку зубов. Получается, 4 * 365 = 1460 минут. Как математик, я вам могу уверенно заявить, что 1460 минут это примерно 24 часа. Итого, каждый год ровно сутки я пердолю свои зубы!

Меня это немного шокировало. Представляете, целые сутки вот так незаметно тратятся на такую повседневную рутину за год! Это натолкнуло меня на определенные размышления.

Нас в жизни зачастую сопровождают довольно много нелюбимых занятий, но которые, тем не менее, надо делать. И мой способ справляться с ними - ковырять их помаленьку, но регулярно. Это всегда даст результат на дистанции. Некоторые предпочитают откладывать такие дела, а потом выделять большое временное окно для решения всей проблемы сразу. Понятно, что это все индивидуально, и зависит еще и от мыслетоплива, необходимого для включения в контекст (чистка зубов вообще контекста не подразумевает, слава богу). Но мне кажется, что равномерная нагрузка - это более щадащий способ для организма и психики справляться с подобными задачами. Я рот топтал чистить зубы сутки подряд, или по 2 часа раз в месяц. Даже если это принесло бы пользу зубам. Но 4 минуты каждый день - окей, штош.

Второй момент. 4 минуты каждый день - это сутки в год. И это сутки "полезного" дела. Если мы тратим каждый день время на что-то "бесполезное", и не 4 минуты, а больше, то у нас это может вылиться в "недели хуйни" в год. Я щас не говорю про то, что не надо там отдыхать, смотреть фильмы, гамать, спать. Это просто скорее мысль о том, чтоб более аккуратно относиться к тому, куда утекает время. Если оно тратится на то, что не приносит радость или какие-то другие цели не позволяет достичь - нахер это все.

И третий момент. Все что можно автоматизировать - лучше автоматизировать. Если бы можно было автоматизировать чистку зубов (или хотя бы сделать ее невидимой) за вменяемые деньги, то shut up and take my money.

Короче, никаких вам советов или инструкций, как жить. Я тут вам не коуч. Думайте сами, ауф🐺
8🔥3
Когда ты один тащишь весь проект 💪 (хотя откуда мне знать 🥲)

Это кстати стена кремля в Пскове. Гонял туда на выходных, чтоб немного отдохнуть от программирования, и узнать историю о том, как княгиня Ольга заживо закопала древлян 😱
2
Сегодня расскажу про реальный кейс в разработке, который не тянет на выступление на конференции, но вполне сгодится для канала. Для описания буду использовать фреймворк S.T.A.R (Situation, Task, Action, Result).

Situation
Как вы все наверное слышали, компания Notion ушла из РФ. На тот момент все существующие аналоги работали очень плохо. А главное, не работал экспорт данных в эти самые аналоги. Notion великодушно предоставил возможность экспортировать данные в виде html файлов 😢

Многие использовали Notion как площадку для организации онлайн курсов. Так случилось, что один известный UX дизайнер Илона тоже использовала Notion для своего курса. Тут ее обзор на альтернативы Notion в момент ухода. Поэтому от Илоны поступило распоряжение, что-нибудь придумать, ведь я же программист😎

Итого, мы имеем пачку html файлов, организованных в странную структуру папок, которые ссылаются друг на друга. Там же где-то внутри находятся все медиа. И если открыть корневой html в браузере, это даже работает. Но нам нужно давать доступ до курса только тем, кто заплатил за него.

Task
что-нибудь придумать Организовать доступ до html файлов для тех, кто оплатил курс

Action
Понимая, что дело пахнет веб программированием, я сразу начал смотреть, а че там по хостингам. Будучи откровенным жадюгой, я решил, что не намерен платить гигантские косты за раздачу html 40 людям💰

Традиционно, самый дешевым способом захостить свой код являются клауд функции, где ты платишь только за вычисления. Однако, как только ты выходишь за пределы вычислений, там с тебя 3 шкуры сдерут. Кроме того, непонятно, на сколько перфоманс клауд функций позволяет быстро отдавать статику. Вдруг там будут затупы на старте. Поэтому сразу отказался от этого.

Принял решение, что сниму самый дешевый VPS и захостю все там. И это будут шикарные 1 CPU (3+ Ghz), 1 Gb RAM, 10 GB NVMe за 7 рублей в день. Обратите внимание, что на данном железе должно крутиться не только само приложение, но и ubuntu вместе с бд.

Кстати про бд, я решил не рисковать и не связываться с записью данных в файлик или sqlite, а сразу использовать нормальную бд MySQL. Почему так? дело в том, что помимо MySQL на этом же сервере можно развернуть phpmyadmin (pma) - и вот мы имеем админку для бедных из коробки! И в будущем эти 300 мб ОЗУ полностью оправдали себя.

Ну и теперь про само приложение. Как я уже сказал, нам нужно отдавать статику. Но часть этой статики должна быть прикрыта аутентификацией, а часть должна оставать в свободном доступе. Я сразу отмел всякие пхп и питоны, потому что, извините меня, но поднимать ларавель на отдачу каждого файлика - это никакой оперативы не напасешься.

Из технологий, с которыми я более менее знаком остались nodejs и golang. Поскольку, в день выбора технологии я был в адеквате, то победил golang 🤡 А если серьезно, то когда в nodejs научится не терять коннекшн к бд, тогда и поговорим.

Деплой было решено делать с помощью контейнеризации и такого великолепного инструмента, как docker compose. В итоге весь сетап представляет собой 4 контейнера: MySQL, pma, nginx и само приложение на golang. Nginx отвечал за ssl сертификаты.

Result
Итого, буквально из говна и палок в кратчайшие сроки было изготовлено решение, которое позволило "заказчику" провести очередной поток Пояснительного курса. Более того, данное решение получилось захостить на клубне картошки 🥔

Но это было только начало. Аппетиты клиента росли, и вскоре появились новые тебования 😱 Но об этом я расскажу в следующей части, которая будет больше про бизнес и про то, как может эволюционировать такой продукт
😁5👏2🙉1
⚠️И сразу в догонку поясню, что пост выше надо воспринимать с некоторой долей юмора и обязательно в контексте задачи. Это не про "бест практисес". Хостить базу данных на том же сервере, что и ваше приложение, скорее нельзя, чем можно. Если вы так делаете, то вы должны отдавать себе отчет обо всех рисках, которые вы несете в этом случае!
👍2🐳1🌚1
Еще один жизненный мем вам в копилочку👆
😁6👻1
https://github.com/ariga/atlas-provider-gorm - пакет для языка golang, позволяющий декларативно описывать миграции для gorm. У пакета 60+ звезд на гитхабе. А https://github.com/readyrevena/atlas-provider-gorm - это форк пакета atlas-provider с внедренным вредоносным кодом. У форка 120+ звезд на гитхабе. Если сильно поторопиться, то можно с радостью внедрить в свой проект уязвимость.

К чему я это все говорю. Проблемы с безопасностью на крупных платформах вроде гитхаба никуда не делись. И топовым фактором, понижающим безопасность, был и остается человеческий. Даже в этом случае, когда уязвимость программная, ее внедрение целиком и полностью зависит от внимательности разработчика.

Поэтому, прежде, чем тащить очередной пакет себе в проект стоит обратить внимание на следующие моменты:
* проекты, у которых единицы звезд на гитхабе - это вообще кот в мешке в плане безопасности и функционала
* проекты, у которых десятки звезд на гитхабе - это кот в мешке, но поменьше при условии, что вы чекнули следующие 2 пункта
* проверяем issues у репозитория, смотрим, живой или не живой проект. это полезно не только в плане безопасности, но и для понимания потенциальных проблем с функционалом
* смотрим, кто эти звезды ставит. если видим, что там преимущественно аккаунты, созданные пару месяцев назад - сразу бан

Короче говоря, безопасность - это серьезное дерьмо. Если вы нашли пакет, который позволяет вам быстро решить очередную вашу проблему, но у него меньше нескольких сотен звезд, стоит подумать о том, чтоб вместо внедрения очередной зависимости тупо скопировать оттуда код, который решает вашу проблему. Единственное, нужно убедиться, что лицензия пакета позволяет это сделать (MIT, apache-2.0, BSD это 👍, а вот gpl - вирусное дерьмо). Я так делал много раз, и все восхищались на ревью, какой же классный код я написал 🤡

Кстати говоря, на этой неделе я буквально решал подобную дилемму. Мне нужно было оформить логи в json в формате для нашего нового сервиса, который мы пишем на python. Офтопом можно отметить, что эта задача должна быть уже решена для любых популярных технологий. Ведь многие системы для сбора логов (например, ELK) принимают логи именно в формате json. Однако python продолжает неприятно удивлять. Потому что библиотека https://github.com/nhairs/python-json-logger, которая решает данную проблему, имеет всего 90+ звезд. И вот я сидел и думал полдня, тащить мне ее в зависимости или самому написать. В итоге я решил тащить. Но к счастью потом выяснилось, что мне все таки не нужен json в логах, и я с облегчением убрал эту зависимость 😌
4😁1🐳1
Кстати, лучшая роль Лебедева, на мой взгляд
😁82
Продолжаю изучать python, и рассказывать вам о своих успехах. Сегодня поговорим про туллинг, а именно про code quality tools.

Вот моя выжимка из кучи статей в интернете и чатгпт
* black - форматтер кода, есть интеграция с pycharm
* pylint - линтер общего назначения
* mypy - линтер и статический анализатор, отвечает за проверку типов при использовании аннотаций типов

И все вроде бы хорошо. Интегрировался с github actions, пофиксил ошибки, код стал чище и красивее. Но у меня с питоном всегда приколюхи находятся😏

К black нет никаких претензий. Он работает как крутяшка, все форматирует сам 😊Кароч, по красоте.

А вот с pylint у меня будет серьезный разговор. Я не понимаю, как линтер может существовать без опции --fix. У меня кода немного, что-то около 10 файлов по паре сотен строк кода. Но когда я запустил pylint первый раз, я просто охерел. Там было что-то около 100+ ошибок. И это после того, как black часть из них пофиксил.

Ну вот не понимаю, почему я должен вручную импорты в определенном порядке расставлять. Или почему я должен вручную менять f-нотацию на lazy интерполяцию (это которая с "%") в эксепшнах. Уж такие то вещи можно автоматизировать в 2025! Ух, помню, как я тогда выбесился, когда это все фиксил 🤬 Просто пиздосий.

Вот реально, все ругают php, типа всратый язык, и вообще, он уже давно умер. Но я вам ответственно заявляю, что в плане code quality тулинга ни один язык и близко не стоит рядом. Ну ладно, не будем пинать живой труп. Но в том же js/ts все работает замечательно. Да даже в golang ихний линтер имеет опцию --fix, и че то там пытается пофиксить, а компилятор так вообще сам форматирует код.

Понятно, что линтеры не все могут сами исправить (хотя в случае с пхп, кажется, что все), но че то в питоне совсем уж все плохо с этим 🤬

Ух! Ладно-ладно, может я чего-то не знаю про python, может я че-то упустил. Может надо было попробовать еще поставить другие форматтеры, типа autopep8 или flack8. Но че то по описанию, порядок импортов они не фиксят.

Но скажите мне тогда пожалуйста, какого рожна pylint такой медленный! напоминаю, у меня 10 файлов, по 200 - 500 строк кода всего лишь. И запуск pylint занимает 8 секунд на моем macbook pro с m1. 8 секунд!!! Что он там делает столько??? Понимаю, что звучу щас непрофессионально. Может надо сесть, поковыряться, разобраться, как настоящий тру программер. Но мне некогда этим заниматься, я хочу фичи для бизнеса делать.

Короче, вот вам идея для опенсорс проекта на питоне: делаем аналог rector. Не благодарите.

P.S. про mypy позже напишу, но там не так все ярко
Когда нашел библиотеку, которая делает все то, что вы нагенерили вместе с чатгпт
👌3
Мой уровень использования LLM. Как говорится, мы получаем те ответы, которые заслуживаем🤷
🤣6😁5👏1
Я рад сообщить, что решил часть своего контента вынести за пределы телеги. Поэтому завел свой микробложик https://nervprog.dev (да-да, я зарегал домен 😊), и планирую туда писать миддл и лонг риды. Причина проста - телега не очень подходит для длинных постов, да еще и с кодом. Посмотрим, как оно пойдет (и пойдет ли).

В планах - прикрутить RSS и делать варианты статей на английском с помощью чатгпт. Пока что написал небольшую пробную статейку Как правильно подключиться к базе данных в Fastapi. Статья будто бы для питонистов, но на самом деле, она больше про глобальные переменные поиск подходов. Напишите в комментах, стоит или нет такое пытаться на medium.com / dev.to / vc.ru публиковать или надо че-то посерьезнее?

P.S. Стоит зайти хотя бы раз, чтоб оценить, какой классный дизайн я выбрал 🤩
🔥8🍾21🗿1
Soooo true😭
😁11🗿1
Обработка ошибок в языках программирования - это вопрос дискусионный. Какого-то консенсуса, как делать правильно, здесь нет по сей день. Где-то язык не предоставляет никаких механизмов для решения этой задачи, отдавая этот вопрос полностью на откуп программистам (привет Си), где-то ошибки - это почти обычные значения, которые возвращаются вместе с результатом выполнения функции (привет golang). Однако наибольшее распространение получил механизм исключений, представленный в таких языках как java, c#, javascript, php и др. Этот подход имеет свои недостатки, но этот пост не о них.

Этот пост об исключениях в python 🥲 Да, в python есть исключения. Есть свой блок try - catch except - finally. И эти знакомые слова могут создать иллюзию похожести. Но это обманчиво.

Первое отличие, которое бросается в глаза, это что стэк трейс в питоне "перевернут". В логах даже всегда есть строчка перед ним Traceback (most recent call last), чтоб вы не забывали. Но это ладно.

Я привык к тому, что exception - это иммутабельная структура данных. То есть, если я где то пишу throw new Exception(), то в этот момент в него помещается вся информация об ошибке и стэк трейс. И дальше уже не важно, что я там буду делать с ним - вся инфа зафиксирована, стектрейс никак не поменяется.

А в питоне? А в питоне есть офигительная возможность, добавлять заметки к эксепшнам 😂

ладно-ладно, давайте посерьезке 🤓

Честно говоря, не знаю, как там это устроено под капотом, но поведение исключения мутабельное с точки зрения логирования стектрейса 😱 Рассмотрим пример


def main():
try:
do_smth()
except Exception:
logging.error("Uncaught exception", exc_info=True)

def do_smth():
try:
do_smth_deeper()
except Exception:
raise

def do_smth_deeper():
raise RuntimeError("deep error")


В этом случае в стек трейсе будет 3 записи: do_smth_deeper -> do_smth -> main. Логично? Логично!

Внесем мааааленькое изменение в наш код: используем именованный raise.

def do_smth():
try:
do_smth_deeper()
except Exception as e:
raise e


Стектрейс изменился, теперь там 4 записи do_smth_deeper -> do_smth -> do_smth (raise e) -> main. Появилась еще одна запись перед main, относящаяся к строчке raise e.

Еще одна трансформация:

def do_smth_deeper():
try:
raise RuntimeError("deep error")
except Exception as e:
raise e


соответственно стэк трейс будет do_smth_deeper -> do_smth_deeper (raise e) -> do_smth (raise e) -> do_smth -> main.

Получается, в python стэкрейс зависит от количества (простихоспади) ре-raise-ов на пути всплывания к логгеру! 🤡

И это еще не все. Но продолжение уже в следующем посте, шоб сильно не грузить и дать мозгу отдохнуть
👍3👌21
Ну шо? Отдохнули?

Тада давайте вам небольшой интерактивчик.

Я немного модифицировал код из предыдущего поста.


def main():
try:
do_smth()
except Exception:
logging.error("Uncaught exception", exc_info=True)

def do_smth():
deep_err = None
try:
do_smth_deeper()
except Exception as e:
deep_err = e
try:
raise RuntimeError("shallow error")
except Exception:
raise deep_err

def do_smth_deeper():
raise RuntimeError("deep error")


Я просто сохранил "deep error" в переменную, чтоб "воспользоваться" ей позднее.