Огромный гайд по настройке рабочего окружения: Linux, VScode, Python
- четверг, 12 июня 2025 г. в 00:00:06
Привет всем!
Как обычно это и бывает, я накопил критическую массу мыслей, и пора их как-то систематизировать, чтобы вы, мои замечательные читатели Хабра, могли что-то извлечь из моего опыта или поделиться своим :)
Я люблю и одновременно ненавижу статьи-обзоры в стиле «10 программ для {whatever}». Ненавижу — потому что их очень легко делать, вбил в гугл «программа для X», взял первые 10 ссылок, статья готова. Я называю такие статьи «лёгкий рейтинг». А люблю я их за то, что даже если 9 пунктов — чушь полная, то десятый, как правило, годный, я узнаю что-то новое, это что-то облегчает мне жизнь и позволяет мне быть более продуктивным.
Сегодня я побуду автором такой статьи — я расскажу вам про то, какие штуки я использую в разработке на питоне, если что-то из этого будет кому-то полезно — я буду рад. В своё время мне этого не хватало. А если вы знаете что-то круче — разнесите меня в комментариях.
Статья получилась ОГРОМНАЯ, и у меня был большой соблазн разбить её на сотню статей поменьше, чтобы в каждой ставить ссылки на свой телеграм-канал и получать гонорар за каждую по отдельности. Но я не буду. Пусть знания будут сгруппированы вместе. Welcome!
Во-первых, я не настолько глуп, чтобы утверждать, будто мой сетап единственно верный. Нет. Каждому своё, кому-то нравится минимализм, а кому-то — рубка космического корабля с тысячей кнопочек и лампочек.
Прелесть линукса и vscode в том, что вы можете собрать под себя тот инструмент, который вам нравится. На что я вас и пытаюсь сподвигнуть :)
Во-вторых, я топил и топлю за unix-философию, когда одна программа делает только что-то одно, и за счёт этого делает своё дело хорошо. Разумеется, на среды разработки такая философия ложится крайне посредственно, потому что мы в IDE и с git хотим работать, и тесты запускать, и много чего ещё. Мне это не нравится. Поэтому для всего, что не касается редактирования и изучения кода, у меня отдельные инструменты, и в данной статье за рамки этой философии я выходить не буду. Никаких rest-клиентов и просмотрщиков 3D моделек в IDE!
Ну, погнали!
Программирование начинается не с IDE, а с рабочего окружения в физическом мире. Я не буду тут обсуждать столы, стулья, марки ноутбуков итд — но расскажу о том, без чего не могу жить и что, имхо, хорошая инвестиция в себя любимого.
Я считаю, что картинка лучше тысячи слов:
Подставка решает две проблемы:
Она освобождает приток воздуха под ноут, что важно, если там воздухозаборники. Мой, собака, греется как печка, и подставка хоть как-то помогает (но не сильно)
Подставка поднимает ноутбук, а вместе с ним и голову погромиста. Осанка всё равно так себе, но хотя бы не так плоха, как могла бы быть.
Стоимость минимальна по сравнению с приносимой пользой, а ещё эта вещь довольно компактно складывается и помещается в рюкзак. Комфортно ли рукам работать с «поднятым» ноутом? Внезапно, да.
Есть ещё младший брат — подставка под телефон. Идея та же — не нужно опускать голову, чтобы что-то посмотреть. При этом может иметь вырез для зарядки.
Часто я ухожу работать в библиотеку. Несмотря на обманчивое название, которое обещает мир и покой, время от времени там проводятся всякие бесовские обряды: русские народные пения, детские кружки с визгами и криками, дуэли в роблоксе на маломощных компах и ещё куча всего. Веселье полным ходом, в общем.
Но мне всё равно, ведь стоит мне включить шумоподавление — и все свистопляски исчезают. Порой я даже музыку не включаю и просто работаю в тишине. Поэтому шумоподавление— это хорошая инвестиция в своё психическое здоровье и улучшение концентрации.
Я уже не в том возрасте, когда я готов работать за идею. Мне деньги подавай. Но иногда проект попадается настолько скучный, что меня просто тошнит от него, и ничто не может меня заставить работать — ничто, кроме pomodoro timer.
Если техника вам неизвестна, то вот суть: вы разбиваете ваш рабочий день на чанки по 25 минут, между ними перерывы 5 минут. Зачем? Концентрация:
Но для меня это не только про концентрацию. Pomodoro превращает скучный рабочий день в примерно десяток скучных рабочих промежутков, на зато каждый промежуток — это всего 30 минут. Мой мозг не понимает, зачем работать целый день, если можно не работать целый день, но заставить его поработать 30 минут и получить отдых — достаточно просто.
Во все самые тёмные времена меня спасал вот этот таймер для Android: Focusmeter. Без него ваш погромист не погромист.
Так уж получилось, что я люблю мобильность, поэтому зачастую сижу за ноутом, а вместо мыши у меня тачпад. В таком сетапе экранного места мало, поэтому я экономлю на всём, и неиспользуемого пространства почти нет.
Я плотно сижу на Linux и переезжать не собираюсь. Потому что мне нравится страдать с драйверами nvidia все сервера как правило на линуксе, и мне удобно, когда везде одно и то же окружение и знакомые утилиты. Ну и кастомизация, да.
Конечно, на Windows совершенно точно существует разработка, но я её никогда не видел вживую. Один мой windows-товарищ на вопрос «а как ты кодишь python на windows?» ответил «а я уже переехал на Ubuntu», а второй сказал: «я загружаю Windows, открываю VirtualBox с Linux Mint и работаю».
Да, это субъективно, но и вся статья такая, сорри :)
14 дюймов диктуют жёсткие условия. Поэтому я выбрал xfce4. Оно мне нравится по трём причинам:
Оно легковесное! Зачем мне прозрачные окна, всякие вылетающие в лицо свистоперделки, если я хочу просто работать / смотреть видео / читать текст / писать статью? Минимализм и лаконичность — это уже красиво само по себе.
Можно выпилить шапки окон! Вы никогда не задумывались, что они бесполезны? Для закрытия / сворачивания / разворачивания и вообще всего есть хоткеи, и получается быстрее, чем тащить мышкой. Заголовок окна мне не сдался вообще. Поэтому — никаких шапок и границ. В xfce для перетаскивания окон можно зажать alt и тащить окно за любую часть (а не только за заголовок) — так даже удобнее. Если вы решите повторить мой подвиг, то создавайте пустую тему (touch ~/.themes/empty/xfwm4/themerc
), и в window manager выбирайте эту "empty" тему.
Внезапно, в xfce можно сделать вертикальную панель управления почти без всяких грязных хаков, и когда привыкаешь, то становится непонятно, зачем их делают горизонтальными! Они ж больше места занимают по вертикали, а его и так мало!
В общем, проще увидеть:
Я постоянно зависаю в терминале, а зачастую у меня открыто сразу 4 окна со всякими докерами-шмокерами, django runserver
, django shell
, ssh
-сессиями итд. Чтобы не путаться с окошками, я юзаю Tilda — это терминал, который по нажатию на F1
(или любой другой хоткей) выезжает из ниоткуда и может потом так же уехать в никуда. Вот, смотрите:
На десктопе, где 2560px в ширину, настроил, чтобы tilda выезжала слева:
В tilda ещё прикольно вот что:
Можно открывать сколько угодно вкладок (ctrl+T
), и перемещаться между ними по хоткею, как между вкладками в браузере. Закрываются вкладки тоже как в браузере (ctrl+W
).
Можно конфигурировать прозрачность и высоту. По F11
можно его развернуть на весь экран, но у меня он по умолчанию занимает половину экрана, потому что тогда я могу на одной половине экрана тыкать в браузер, а на другой видеть терминал и что там выводится, когда я тыкаю. Это бывает удобно.
Можно настроить infinite scroll, чтобы не было лимита на количество строчек (ну как и в других терминалах, я полагаю). Не важно, сколько данных мне напечатает команда в терминал, ничего не пропадёт, потому что я могу отмотать в самое начало.
Работает поиск — ctrl+shift+F
Главное, конечно — много терминалов на расстоянии одной клавиши, не занимают место на экране и не замусоривают список открытых программ.
Экран маленький, ничего из UI нет. Поэтому назначим на всё горячие клавиши! Тем более это всегда быстрее, чем тыкать мышкой.
Долгое время кнопка «windows» у меня на клавиатуре простаивала (какой нафиг «Пуск» на linux!), но теперь она у меня — запускатор. Win+S открывает, например, Slack, Win+C — vscode, Win+T — окошко терминала, итд. Причём команда на шорткат примерно такая: sh
—c "wmctrl -a Slack || slack"
, что на русский переводится так:
Перенеси меня колечко
Через лесок, через крылечко,
В окошко, где мой Слак родной,
А если нет, тогда открой.
Все эти шорткаты позволяют почти не использовать alt-tab, потому что я сразу прыгаю в нужное мне приложение. Чего и вам желаю.
Всё, что не на хоткеях, запускается через GUI запускатор. Раньше я использовал Synapse, сейчас перешёл на Ulauncher, потому что он красивей и для него уже написаны (и можно написать свои) плагины на питоне, например, менеджер flatpak, AI-чат (ollama, chatgpt, ...), fuzzy поиск, системный монитор итд. Это ж бомба! Свои плагины пишутся за 3 секунды и ставятся прям из github.
Назначаете ентот лаунчер на удобную клавишу, и все программы на расстоянии нескольких нажатий клавиш.
Также есть встроенный калькулятор, выручал не раз:
Ещё есть классный плагин fzf (fuzzy find). Я ввожу z моя-упоротая-презентация
, и оно само ищет мою упоротую презентацию по всей файловой системе. То есть я могу открыть любой файл, не ища его в иерархии файловой системы. С папками тоже работает.
Это жутко удобно.
Ну конечно, куда ж без LLM! На десктоп я прикупил себе 16Гб VRAM, чтобы хоть какая-то модель туда влезала. Вопреки распространённому мнению, что AMD не умеют в языковые модели — они умеют. И ollama — софт для скачивания и запуска моделей локально — тоже поддерживает карточки Radeon. Так что пофиг, за красных вы или зелёных — качайте ollama, и будет вам счастье.
Чего в этой ламе не хватает — так это нормального интерфейса. Поэтому рекомендую скачать open-webui, чтобы иметь что-то похожее на диалоговое окно chatGPT, с возможностью прикреплять картинки. Чтобы не засорять систему, запускать можно через докер, но я пошёл дальше и запускаю его как демона (переменная WEBUI_AUTH=0
— чтобы пароль не просил):
❯ cat /etc/systemd/system/open-webui.service
[Unit]
Description=Open WebUI Docker Container
After=ollama.service
Requires=ollama.service
StartLimitBurst=3
Restart=on-failure
RestartSec=10
[Service]
Type=simple
Restart=always
ExecStart=/usr/bin/docker run --rm -p 3000:8080 --network=host -v open-webui:/app/backend/data -e OLLAMA_BASE_URL=http://127.0.0.1:11434 -e WEBUI_AUTH=0 ghcr.io/open-webui/open-webui:main
[Install]
WantedBy=multi-user.target
Теперь у нас свой chatgpt в браузере по адресу http://127.0.0.1:8080
Многие приложения выставляют веб-морду, но часто хочется, чтобы было отдельное окно, как приложение. В браузере vivaldi можно любую страничку установить как отдельное приложение, если кликнуть правой кнопкой мыши на вкладке и нажать Install ...
. Поэтому open-webui, яндекс.музыка, syncthing и прочие веб-приложения у меня выглядят как нативные приложения, хотя по факту это просто веб-странички.
У нас, линуксоидов, есть репозитории, откуда мы ставим наш софт. Но иногда там может чего-то не быть!
Если софта нет в официальном репозитории дистрибутива, можно подключить сторонний репозиторий (например, https://download.docker.com/linux/ubuntu
для докера)
Можно посмотреть рецепт, как собрать из исходников самому (например, Arch User Repository)
Можно запустить через Docker
Можно превратить WebUI в приложение, как в предыдущем пункте
Но последний оплот — это Flatpak / AppImage / Snap, когда приложение целиком запаковано вместе со всеми необходимыми библиотеками. Очень выручает в случаях, 1) когда нужно проприетарное приложение, недоступное в репах (типа zoom), и 2) когда приложение не запускается из-за каких-то несовместимостей библиотек (типа zoom).
Из важного могу отметить мою ненависть к Snap, который авто-обновляется и который почему-то начинает заменять нативные приложения на Ubuntu. Фу!
Как я уже сказал, я живу в терминале, и мне хорошо. Вот что мне помогает.
Многие это, наверно, знают, но когда я впервые об этом узнал, это перевернуло игру (с):
ctrl+A
перемещает курсор в начало строки
ctrl+E
перемещает курсор в конец строки
open .
откроет текущую папку в подходящей программе
open {file}
откроет файл в подходящей программе
С open
use-case достаточно частый — иногда я хочу какой-то GUI для работы с файлами — например, посмотреть превью фоток в папке. Терминал мне это не покажет, поэтому я делаю open .
, открывается файловый менеджер, и я всё красиво вижу. Могу написать open file.csv
, и вот файл открыт в офисной программе.
Раньше я мог настроить bash до вменяемого состояния. Или поставить zsh, накатать oh-my-zsh и дотюнить его по вкусу.
Но сейчас мне лень. Поэтому я ставлю fish shell, в котором из коробки:
подсветка синтаксиса
автодополнение (tab-completion)
нормальное перемещение по истории
синтаксис получше, чем у bash
Из минусов:
Он несовместим с синтаксисом bash, так что просто скопировать shell-инструкцию из этих ваших интернетов и запустить в fish не получится (но всегда можно bash -c "скрипт из интернета"
). С другой стороны, с запуском bash-скриптов никаких проблем нет, bash
myscript.sh
будет работать как обычно, так что жить более-менее можно.
Нет heredocs, и это бесит.
Настраивать строку ввода? Мне лень. Поэтому я ставлю starship, который может показывать кучу всего из коробки. Мне нравится, что если я нахожусь в папке проекта, то он покажет только название проекта, а не весь путь до него. Ну и текущую ветку git и версию питона.
Можно ещё поставить плагин fish-ai и получить AI в командной строке — либо сторонний (например, условно-бесплатный groq), либо локальный через ollama. Хотя мне не зашло — качество gemma3:12b
тут оставляет желать лучшего.
Zoxide — это замена команде cd
, с которой вы потом не слезете.
При установке появляется алиас z
, и теперь чтобы перейти в папку ~/some/very/very/long/path/to/work
, я пишу просто z work
. Так же как и в ULauncher, я не должен помнить, где именно находится папка, zoxide сам всё найдёт и просто переместит меня в нужное место, не важно, насколько глубоко в файловой системе оно находится.
По работе у меня штук 20 проектов, и я за одну команду могу прыгнуть в любой из них!
Как я уже сказал, у меня два десятка проектов для клиентов, и ещё примерно столько же моих собственных пет-проектов. Для всех свои настройки — где-то нужно использовать один ssh ключ, где-то другой, в каждом своя версия питона, свои ключи к API, профили AWS и т.д. И тут мне помогает direnv.
Суть утилиты — она ищет в текущей папке файл .envrc
(и .env
, если настроить) и автоматически запускает его. Внутри файла вы можете что-то выполнять, но основной сценарий — задавать переменные окружения. Когда вы «выходите» из папки (то есть оказываетесь выше по иерархии), то все эти переменные окружения выгружаются. Зачем задавать переменные окружения? Потому что, согласно 12-factor app, конфигурацию приложения нужно хранить в переменных окружения.
Сценарий использования:
Я зашёл в папку проекта, и все переменные окружения заданы. Теперь я могу запустить, скажем, ./
manage.py
runserver
, и приложение успешно запустится, потому что оно берёт настройки из переменных окружения, а они уже автоматически заданы.
Тут есть один нюанс: .envrc
— это просто скрипт с экспортом настроек, выглядит вот так:
> cat .envrc
#!/bin/sh
export POSTGRES_DB=project
export POSTGRES_HOST=localhost
export POSTGRES_PORT=5432
export POSTGRES_USER=postgres
export POSTGRES_PASSWORD=12345
Но часто эти переменные окружения нужно передать ещё в docker compose, а он понимает только .env
файлы. .env
-файл — это не скрипт, а просто перечисление ключ=значение
:
> cat .env
POSTGRES_DB=project
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=12345
Получается, что одни и те же настройки приходится задавать в двух местах:
в .envrc
для автозагрузки через direnv
в .env
для docker-compose и прочих программ, читающих env-файлы
Поэтому либо настраивайте direnv, чтобы он читал .env-файлы, либо внутри .envrc
запускайте dotenv
:
# .env
POSTGRES_DB=project
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=12345
# .envrc
#!/bin/bash
dotenv # загружает всё из .env
Итого: при заходе в папку любого проекта у меня автоматически уже настроено окружение для работы с ним. Кайф.
Когда я в стопятьсотый раз удалил что-то при помощи rm -rf
и пошёл гуглить, как восстановить файлы в ext4 (вкратце: жопа!), я задумал решить проблему раз и навсегда.
trash-cli
— это замена rm
, которая не удаляет файлы безвозвратно, а перекладывает их в корзину. Она совместима с интерфейсом rm
, поэтому я сделал просто alias rm="trash"
, и теперь rm -rf *
поместит всё в корзину, а не в небытие. Вот, например, я случайно удалил файл, а потом передумал и восстановил:
> rm project/core/migrations/0006_dayoff_commitment.py
> trash-restore project/core/migrations/0006_dayoff_commitment.py
0 2023-09-19 15:23:07 .../app/src/project/core/migrations/0006_dayoff_commitment.py
1 2023-09-19 16:04:44 .../app/src/project/core/migrations/0006_dayoff_commitment.py
2 2023-09-19 16:39:05 .../app/src/project/core/migrations/0006_dayoff_commitment.py
What file to restore [0..2]: 2
Сколько раз это спасало мою программистскую попу - не передать словами!
Разумеется, помимо удаления-восстановления утилита позволяет очищать корзину: trash-empty
.
Есть ещё rip.
xh
- это замена curl
/ wget
. Я использую эту утилиту, когда мне нужно прям быстро потестить какой-то запрос, например, отправить что-нибудь на локалхост при разработке. Синтаксис супер-простой:
xh POST --json "https://some-website/api/endpoint" \
title="Something" \
ApiKey:12345
Строчка выше отправит POST-запрос с content-type=application/json
на указанный endpoint, при этом тело запроса будет{"title": "Something"}
, а один из заголовков будет ApiKey=12345
. Это удобно.
xh help
выдаст полную справку по синтаксису. Поначалу непривычно, потом уже пишешь на автомате:
key==value
Add a query string to the URL.
key=value
Add a JSON property (--json) or form field (--form) to
the request body.
key:=value
Add a field with a literal JSON value to the request body.
Example: "numbers:=[1,2,3] enabled:=true"
key@filename
Upload a file (requires --form or --multipart).
To set the filename and mimetype, ";type=" and
";filename=" can be used respectively.
Example: "pfp@ra.jpg;type=image/jpeg;filename=profile.jpg"
@filename
Use a file as the request body.
header:value
Add a header, e.g. "user-agent:foobar"
header:
Unset a header, e.g. "connection:"
header;
Add a header with an empty value.
Для более основательных экспериментов, разумеется, рекомендую что-то с GUI:
jq
получает на вход сырой json, красиво форматирует и возвращает то, что вам оттуда нужно. Представьте, что вышеупомянутый xh
возвращает из API вот такое:
> xh https://...
{"activities":[{"id":3807068273,"date":"2022-10-01","message":"abc"},{"id":3807075992,"date":"2022-10-01","message":"cde"},{"id":3807083990,"date":"2022-10-01","message":"efg"}],"pagination":{"next_page_start_id":3807083991}}
Тогда применим jq
, чтобы получить, например, только id
и date
:
> xh https://... | jq ".activities | .[] | [.id, .date]"
[
3807068273,
"2022-10-01"
]
[
3807075992,
"2022-10-01"
]
[
3807083990,
"2022-10-01"
]
Даже если вам не нужно ничего из json доставать, то jq всё равно удобен в тех случаях, когда данные возвращаются в формате «json-каша» (это когда нет переносов строки и отступов). Jq выводит данные так, что их становится легко читать.
Есть top
, есть htop
, а есть мультиварка под названием glances
. Мне нравится, что там CPU, GPU, RAM, сенсоры и, конечно, процессы.
Я сам не пользуюсь, но кто-нибудь в комментах обязательно напишет, так что я иду на опережение! Встречайте: The Fuck. Исправляет опечатки по команде fuck
:
Fuzzy-поиск с утилитой fzf: можете вводить искомое как попало, и всё равно найдётся. Причём быстро!
Т.к. я привык работать в VScode, то мне хотелось вести заметки в нём. Но это неудобно по множеству причин, главная из которых — а как это перенести на мобильник?
И тут, конечно, выиграл Obsidian. Почему? Всё просто:
Obsidian похож на VScode: слева древо файлов, справа оглавление
Есть плагины
Есть шорткаты
Умеет рендерить markdown прям сразу во время редактирования
Есть версия для ПК и для Android, и они идентичны
Под капотом это просто .md файлы в папках, то есть никакой магии
Скриншот лучше тысячи слов (осторожно, рекурсия!):
Как-то в 2022 году оплата карточками накрылась медным тазом (спасибо, блин!), и облачный сервис Obsidian Sync перестал работать. А синхронизовать заметки между компом и телефоном как-то нужно!
К счастью, есть Syncthing. Этот софт — чистая магия. Ставите его на оба устройства, вводите настройки, оно само делает вжух-вжух, и файлы синхронизируются. Именно таким образом мои заметки всегда одинаковы и на мобильнике, и на ноуте, и на десктопе, и я за это ничего не плачу.
Взаимодействие идёт peer-to-peer, то есть синхронизация будет работать, только когда оба устройства в сети. Но такое у меня лично очень часто, поэтому я не замечаю лага. Если нужна абсолютная синхронизация, то поставьте ещё один инстанс syncthing на устройство, которое постоянно в сети — какой-нибудь дешёвый сервачок. Изи.
Можно пойти дальше и синхронизировать все заметки между своими устройствами, а какую-то подпапку — с другим человеком.
Минусы:
Синхронизирует любые типы файлов, поэтому каких-то специальных обработчиков для текста нет. Если в гите мы привыкли, что всё мерджится автоматически, то тут как только версии на устройствах не совпадают — появляются конфликт-файлы, которые нужно резолвить вручную. Есть решения, но нужно настраивать.
Иногда не синхронизирует какие-то файлы, и понять, какого хрена вообще — нет возможности. Бесит неимоверно. Возможно, я не умею его готовить.
Ладно, тут наверно у каждого свои предпочтения насчёт просмотрщика VCS, и скорее всего, все юзают то, что встроено в IDE. Но лично я не очень люблю встроенные решения, в основном из-за паршивой визуализации. Да, я олдфаг, и я привык вводить git-команды в терминале, а не кликать мышкой. Поэтому всё, чего мне не хватало — хорошего просмотрщика истории git, вроде как git log --graph --oneline --all
, но всё же поприятнее. Потому что для понимания того, что, блин, нахрен происходит в этом богом проклятом репозитории, лучше всего подходит визуализация дерева коммитов.
Вот сравнение: GUI для Git: подборка популярных решений, там в комментах юзеры накидали ещё много всего. Но я как в том меме: что это фигня, что то фигня.
Мне просто нужна хорошая, понятная картинка, только и всего. Почему-то с этим лучше всех справился gitg. Смотрите сами: слева — diff для выбранного коммита, справа — дерево коммитов, где есть и local, и remote. Больше он ничего не умеет, а мне и не надо!
Он опенсорс, не нужна никакая регистрация, понимает любое git репо. Можно запустить из терминала прямо из папки с проектом: gitg . &
.
Иногда достаточно вызвать git diff
, чтобы посмотреть на текущие изменения. Но бывает, что хочется что-то подправить в этих изменениях, или увидеть «бОльшую» картину, и в этом случае помогает git difftool
, который показывает diff в сторонней программе.
У меня эта сторонняя программа — meld.
# настраиваем глобально один раз
git config --global diff.tool meld
git config --global merge.tool meld
git config --global --add difftool.prompt false
# запускаем
git difftool HEAD~5
В общем-то, подобные штуки встроены в IDE, но мне нравится, когда каждая программа делает только одну вещь. Meld отлично показывает diff'ы, и это всё, что мне от неё надо.
Если вам больше по душе , скажем, vscode, то можно указать его в git config diff.tool
выше — тоже будет работать.
Как я жил без этого? Вечером и ночью монитор слепит синим цветом. Мне кажется, что уже на всех телефонах для этого сделали режим «защита зрения», когда экран начинает отдавать в желтизну.
В моём дистрибутиве принято страдать и настраивать всё самому, поэтому я поставил Redshift. Когда солнце садится, данная софтина делает цвет экрана более тёплым, и программировать становится гораздо приятней.
Мониторы, кстати, тоже позволяют настраивать цветовую температуру, так-то.
Постоянно делаю скриншоты, в этом помогает xfce4-screenshooter, повесил его на клавишу PrntScr
. Он умеет фоткать нужную область или весь экран, с задержкой или нет, с последующим сохранением в файл или открытием в фоторедакторе. Дёшево и сердито.
В одном интернет-магазине у нас были уведомления в slack при поступлении нового заказа. А потом вжух — и slack закрыли для России. Тут на выручку и пришёл ntfy.sh — это сервис для нотификаций. Создаёте что-то вроде канала, отправляете туда что угодно через POST-запрос, и все подписанные на этот канал девайсы это уведомление получают. Есть клиенты для linux и android, можно смотреть через веб.
Код на питоне (6 строчек!):
def notify(message: str) -> None:
try:
response = requests.post("https://ntfy.sh/your-topic-name", data=message.encode('utf-8'), timeout=5)
response.raise_for_status()
except Exception:
log.exception('Could not send notification to %s', url)
Сценарии использования:
Уведомления: в вашем приложении что-то происходит, оно отправляет POST-запрос в ntfy.sh, все подписчики получают уведомление. Гораздо проще, чем настраивать телеграм-бота или, боже упаси, интеграцию со slack.
Тестирование xss: эксплуатируем уязвимость, украденные данные кидаем в ntfy.sh и анонимно их оттуда забираем :] Не нужен свой сервис, чтобы принимать данные.
Webhook на локалхосте: всякие сервисы любят присылать уведомления нам на вебхук. А как этот тестировать, если мы запустили приложение локально на 127.0.0.1:8000 и внешний сервис не пробьётся к нам через NAT? Можно использовать ngrok, чтобы получить временный внешний IP, но это нужно что-то настраивать и запускать у себя. Бюджетный вариант — сказать сервису, чтобы отправлял уведомления на ntfy.sh, а оттуда уже можно ручками или программно забрать данные и кинуть на локальный вебхук.
Кроме того, это оперсорс, так что если хотите приватность — без проблем, разворачивайте свой сервер. А ещё есть API, если хотите программно читать уведомления. Крутая штука!
Есть много всяких утилит для сборки, тестирования и запуска проектов. Самая популярная, наверно — это Makefile. К моему счастью, я дожил до момента, когда вовсю используются альтернативы. На слуху, конечно, всякие taskfile, just и tox, но у нас в компании как-то сложились тёплые отношения с nox.
Nox — это утилита для тестирования и сборки, где конфигурация делается через python-скрипт. Да, забавно: пакеты в питоне переезжают с setup.py
скриптов в императивный pyproject.toml
, а мы тут наоборот с yaml
и ini
перебираемся в формат скрипта. Почему? Потому что удобно!
Создаём noxfile.py
в корне проекта, пишем, какие команды что запускают:
import nox
@nox.session
def tests(session):
session.install('pytest')
session.run('pytest')
@nox.session
def lint(session):
session.install('flake8')
session.run('flake8', '--import-order-style', 'google')
... и по nox tests
запустится pytest.
Да, пример тривиальный. Нужно посложнее? У нас в репо есть такое: создаём новый проект из репозитория, инициализируем его, запускаем докер, потом запускаем тесты. После тестов всё подчищаем и выключаем. Такой вот монстр:
@contextlib.contextmanager
def docker_up(session):
session.run("docker-compose", "up", "-d")
yield
session.run("docker-compose", "down", "-v", "--remove-orphans")
@contextlib.contextmanager
def crufted_project(session):
session.run("pip", "install", "-e", ".")
tmpdir = crufted_project.tmpdir
if not tmpdir:
session.notify("cleanup_crufted_project")
crufted_project.tmpdir = tmpdir = tempfile.TemporaryDirectory(prefix="rt-crufted_")
session.log("Creating project in %s", tmpdir.name)
session.run("cruft", "create", ".", "--output-dir", tmpdir.name, "--no-input")
project_path = Path(tmpdir.name) / "project"
with session.chdir(project_path):
session.run("git", "init", external=True)
session.run("./setup-dev.sh", external=True)
else:
project_path = Path(tmpdir.name) / "project"
with session.chdir(project_path):
yield project_path
@nox.session(python=PYTHON_DEFAULT_VERSION, tags=["crufted_project"])
def test_crufted_project(session):
with crufted_project(session):
with docker_up(session):
session.run("nox", "-s", "test")
Если вы разрабатываете на питоне и ещё не используете uv — то самое время переходить. Разрешает зависимости, делает локфайл, сам ставит нужную версию питона! Pyenv
, pdm
, poetry
и уж тем более pip
уходят в прошлое.
Но главная фишка, от которой я тащусь — это запуск утилит на питоне. Представьте, что есть какая-нибудь полезная программа, написанная на питоне. Куда её ставить и как запускать?
Либо ставить в userspace, засоряя ~/.local/lib/python3.x/site-packages/
Либо создавать ручками виртуальное окружение и ставить в него
К счастью, uv tool
(или, сокращённо, uvx
) сделает это всё за вас!
uvx command
скачает всё необходимое и запустит команду - например, uvx ruff@0.6.0
запустит ruff. Все наобходимые зависимости будут установлены во временную директорию.
uv tool install
установит пакет перманентно (чтобы узнать, куда именно, наберите uv tool dir
- у меня это ~/.local/share/uv/tools
).
Почитать подробнее можно тут.
Я так запускаю nox
как раз:
uv tool install nox
uvx nox -s test
Ещё одна из утилит, которую я запускаю через uvx
— это uncurl. Когда я анализирую, какие запросы делает сайт, я очень часто хочу их повторить в питоне. Для это в chrome dev tools я копирую запрос как curl и вызываю uvx uncurl
— утилита сама считывет запрос из буфера и превращает в питон-код:
❯ uvx uncurl
requests.post("https://habr.com/kek/v2/users/kesn/note",
data='hl=ru; fl=ru; theme=light; visited_articles=907904:840200:901368:892190:903376:903338:340146:901382:310460:438796',
headers={
"accept": "application/json, text/plain, */*",
"accept-language": "en-US,en;q=0.9",
"priority": "u=1, i",
...
},
cookies={},
auth=(),
proxies={},
)
Поставить можно прям из гита (но не забывайте читать исходники, когда так делаете):
uv tool install https://github.com/spulec/uncurl.git
Как, наверно, и у многих, у меня есть коллекция скриптов на bash, которые немного упрощают жизнь. Ничего необычного, но я хотел выделить парочку, без которых тяжко.
Есть разные типы бэкапов — например, копирование в облако, снэпшоты ФС, — но мне нравится иметь «холодное хранилище», то есть отдельный жёсткий диск, на который я периодически копирую данные, в остальное время он пылится в ящике вдали от ноутбука. Мне нравится такой подход по двум причинам:
Физическое разделение данных. Даже если девайс сгорит или потеряется, данные будут доступны
Доступность. Это не облачный провайдер, для которого нужна сеть — тут всё буквально «в руках».
Контроль. Диск — оффлайн, никакого автоматического копирования нет. То есть не будет такого, что ОС обновилась, сделала бэкап, а потом оказалось, что она после обновления не загружается. Или утилита поставилась, снесла /home
и записала это в бэкап. Нет, всё чётко под контролем. Я сам порчу свои данные.
Да, я сходу придумал несколько сценариев, когда эта схема с треском провалится, но тут уж каждый решает сам, насколько он хочет заморочиться.
Сам бэкап-скрипт супер-примитивен: это простой rsync
с несколькими специфическими флагами:
rsync -aAXHv --exclude-from="exclude.txt" --delete --delete-excluded / "$1"
В деталях всё описано на Arch Wiki: Rsync - full system backup.
Для копирования в облако есть неплохой Rclone
Добавлять мусор в систему — легко, вычищать — сложно. Для этих целей у меня есть скрипт-уборщик, в последний раз он собрал около двухсот Гб мусора, чему я был несказанно рад. Команды простые, в основном это удаление ненужного докер-барахла:
#!/bin/sh -eux
paccache -ruk1 # чистим кэш пакетного менеджера, для Ubuntu подойдёт apt-get clean
journalctl --vacuum-size=500M # оставим только 500Mb логов journald
docker volume prune # удаляем все volume, не связанные с контейнерами
docker image prune -a # удаляем все image, не связанные с контейнерами
docker buildx prune # удаляем кэш buildx
docker container prune --filter "until=2160h" # удаляем остановленные более 90 дней назад контейнеры
docker images | grep "" | awk '{print $3}' | xargs docker rmi -f # удаляем "висячие" image
У нас в компании разработка на заказ, поэтому клиентов много. Каждый раз начинать строить проект заново — затратно, поэтому у нас есть шаблон проекта и набор опций (например, использовать celery
или нет). Когда нужно начать новый проект — мы отвечаем на несколько вопросов в терминале, и у нас из шаблона материализуется новый проект. Всё это делается при помощи Cookiecutter:
uv tool install cookiecutter
uvx cookiecutter https://github.com/reef-technologies/cookiecutter-rt-django
Все ответы на вопросы, которые вы дали перед созданием проекта, можно использовать где угодно — например, в коде. При создании проекта всё подсчитается и подставится.
import os
{% if cookiecutter.use_channels == "y" %}
from channels.routing import ProtocolTypeRouter, URLRouter
{% endif %}
from django.core.asgi import get_asgi_application
# init django before importing urls
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{cookiecutter.django_project_name}}.settings")
http_app = get_asgi_application()
{% if cookiecutter.use_channels == "y" %}
from .urls import ws_urlpatterns # noqa
{% endif %}
{% if cookiecutter.use_channels == "y" %}
application = ProtocolTypeRouter(
{
"http": http_app,
"websocket": URLRouter(ws_urlpatterns),
}
)
{% else %}
application = http_app
{% endif %}
Можно назвать файл {% if cookiecutter.some_condition == 'y' %}
main.py
{% endif %}
, и если у нас условие не выполнится, то файл main.py
вообще не будет создан.
Очень рекомендую для cookiecutter настроить lstrip_blocks
и trim_blocks
, чтобы всякие {% if cookiecutter.some_condition %}
удалялись вместе со всей строкой, иначе после создания проекта будет очень много бесячих пустых строк.
Ну хорошо, создали мы 10 проектов. А через месяц мы фиксим какой-то общий баг и хотим обновить сразу все проекты. Cookiecutter в этом никак не поможет, зато на выручку приходит Cruft. Он, как и cookiecutter, может создавать новые проекты по шаблону, но что важнее — он умеет обновлять существующие проекты при изменениях в шаблоне.
uv tool install cruft
uvx cruft create https://github.com/reef-technologies/cookiecutter-rt-django
# ... через месяц
uvx cruft update
Последняя команда применит изменения к вашему проекту, а если не сможет это сделать автоматически — то создаст миллион файлов-конфликтов *.rej
, которые вам нужно будет разрешить самостоятельно. Да, это ручная операция, не самый приятный процесс, но зато вы точно держите все изменения под контролем.
Так уж получилось, что я на vscode. Это сложилось исторически, когда pycharm тормозил при прокрутке и выглядел как кабина самолёта, с миллиардом кнопок и переключателей. Сейчас всё, конечно, не так, и всем, кто меня спрашивает, какую IDE использовать для питона, я говорю: Pycharm. Она быстрая, там всё удобно из коробки, есть какие-то экзотические фичи типа удалённой отладки.
Вообще мы как-то попробовали на работе устроить холивар на эту тему, и вывод простой: если сравнивать пофичечно, то pycharm и vscode идут бок о бок, только в последнем нужно для всего ставить плагины. Поэтому pycharm выигрывает — там ничего делать почти не надо. С другой стороны, pycharm как бы для питона, а vscode — для всего. Короче, не знаю. На вкус и цвет.
Если вы, как и я, сидите на vscode, то вот какие фичи и плагины я считаю годными.
Вкусовщина, но вдруг вам зайдёт.
Когда у меня подгорает — я включаю холодную Nord
Когда достаточно охладился — то горячую Flare
В остальных случаях — северо-сиятельную Ariake Dark
Так и прыгаю туда-сюда.
А вообще есть классный сайт для выбора тем: https://vscodethemes.com. Рекомендую.
Когда я начал всю эту тему с освобождением пространства на экране, я подумал и понял, что Activity Bar — вот эта панель слева, где Explorer
, Search
, Source control
итд — она не нужна. Две самые используемые вкладки — поиск и древо файлов — доступны по хоткеям (Ctrl+Shift+F
и Ctrl+Shift+E
соответственно). Поэтому я уменьшил Activity Bar и почти не вспоминаю про неё:
"workbench.activityBar.location": "top"
С другой стороны, почему-то Vscode не показывает secondary sidebar справа по умолчанию, а она очень удобна! Туда можно поместить что-нибудь, что вам дорого. Я, например, держу там «outline» — логическую структуру файла, т.е. список классов, методов и функций.
Открывается она по Ctrl+Alt+B
, но можно настроить, чтобы она была открыта по умолчанию:
"workbench.secondarySideBar.defaultVisibility": "visible"
Далее эту панель «outline» нужно ручками перенести из Primary Sidebar в Secondary Sidebar (слева направо).
Ещё нюанс: по умолчанию там показано всё, в т.ч. переменные — и получается каша. Я переменные оттуда убираю, и становится как надо:
"outline.showVariables": false,
Ну и напоследок: когда курсор находится внутри метода, то хочется, чтобы он подсвечивался в Outline (как на картинке ниже). Для этого нажимаем на «...» и жмём «Follow cursor». Увы, настройками это не сделать, и приходится каждый раз вручную активировать.
Очень часто хочется увидеть весь проект «с высоты птичьего полёта», и я имею в виду не разглядывание дерева файлов в боковой панели, а что-то более глобальное.
Во-первых, можно визуализировать репо, как, например, сделано в Github Next: repo visualization. Вбиваете публичный репо — он вам строит кружочки. Вот cpython:
Есть ещё всякие плагины для IDE: Swark, Vxplain, CodeViz. Они пытаются использовать AI, чтобы нарисовать логическую структуру проекта. Работают все по-разному, чего-то прям выдающегося я не нашёл, но считаю, что так-то задумка хорошая.
Когда мне кажется, что я слишком умный и могу всё понять, я открываю вот этот кусок кода, который в своё время поломал мне мозг. Он ломает и сейчас.
class BucketListBase(Command):
@classmethod
def _setup_parser(cls, parser):
parser.add_argument('--json', action='store_true')
super()._setup_parser(parser)
def _run(self, args):
return self.__class__.run_list_buckets(self, json_=args.json)
@classmethod
def run_list_buckets(cls, command: Command, *, json_: bool) -> int:
buckets = command.api.list_buckets()
if json_:
command._print_json(list(buckets))
return 0
for b in buckets:
command._print(f'{b.id_} {b.type_:<10} {b.name}')
return 0
Тут вот есть метод run
, который вызывает классметод runlist_buckets
и передаёт туда свой инстанс и заодно команду типа Command
(хотя инстанс уже и так унаследован от Command
), а внутри этой команды вызывается метод какого-то API. Изи! Но вообще-то я ни черта не понял.
Для vscode есть всякие плагины для построения графа вызовов (call graph), например, Chartographer, Vxplain call graph, Source code visualizer итд итп. Но работают они посредственно, а почему — и так понятно:
def func_factory(param):
if param < .5:
return func_a
else:
return func_b
func = func_factory(some_variable)
func()
Что тут вызовется? А хрен его знает, без рантайма и не скажешь! Вот и автоматические тулзы совершенно не справляются с динамичными частями питона, и на примере с BucketListBase
получается чёрт-те что — оно вроде и показывает что-то, но про API умалчивает.
А что делать? Вариант 1 — спросить LLM (например, Copilot), что происходит. Вариант 2 —вручную пройтись по коду и посмотреть, что происходит. Но в переусложнённом коде слишком много ветвлений и наследования, и удержать всё в голове нереально. Поэтому особая почесть тем плагинам, которые позволяют раскидать код на плоскости вручную.
Сравните Source code visualizer в автоматическом режиме:
И он же, но код раскидан вручную:
Видите? Я как будто прикрепляю заметки с кусками кода, как в том меме. И всё становится понятно. Ну кайф же!
Каждый день я читаю километры плохого кода, а плохой он в том числе потому, что запутанный. Распутывать код, помечать какие-то места, чтобы к ним вернуться, мне помогают закладки — Bookmarks.
По ctrl+alt+K
я отмечаю интересную строчку (например, я нашёл баг и хочу вернуться к нему позднее, или хочу отметить какой-то момент в цепочке вызовов). Все закладки появляются в панели слева, но ещё по ним можно прыгать хоткеями. Смотрю код, вижу — развилка: либо вглубь, либо вбок. Поставил закладку, пошёл вглубь стека вызовов, потом по хоткею вернулся к развилке и пошёл вбок.
Во-первых, есть Better comments, который выделит особые комментарии, например, TODO
:
Но мне ещё нравится Highlight — он не только подсвечивает наперёд заданные комментарии, но я позволяет создавать свои правила вида «регулярное выражение -> цвет». Можете выделять красным цветом антипаттерны, например, или # UGLY
, чтобы было максимально ugly:
Все знают, что есть folding — это когда кусок кода можно «свернуть» в одну строчку, чтобы он не мешал. Получается, что мы видим код «на поверхности», не ныряя в более глубокие участки кода.
Для автоматизации этого есть Fold level. После установки появляется такая панель в статус баре:
Нажимая, например, на «3», мы фолдим всё, что глубже уровня 3. Сравните это
и это:
Получается, мы можем просматривать код поверхностно, а можем погружаться на нужную глубину. Удобно не только в коде, но и при анализе больших json
, где с первого взгляда теряешься и неплохо было бы сначала хотя бы понять, какие ключи есть на верхнем уровне. Этот плагин здорово в этом помогает.
В тему: иногда попадается отвратительная портянка из данных. Indent nested dictionary добавляет команду «отформатируй это непотребство». Работает на json и питоновских словарях, даже если они покорёжены и содержат синтаксические ошибки.
Было (заметьте: обрезано в конце):
Стало:
Ладно, в коде мы ориентируемся, но нам бы ещё хотелось быстрее этот код писать и перемещаться по нему.
Тут на самом деле совет один: выучите уже хоткеи. Я столько раз видел, как разработчик тыкал мышкой по дереву файлов в попытке отыскать тот самый, нужный, когда можно просто нажать ctrl+P
и ввести имя искомого файла!
На сайте vscode есть официальные шпаргалки по горячим клавишам для всех ОС. Скачайте и запомните, если ещё это не сделали — ускоритесь в разы.
Ну да, LLM всё-таки ускоряют ввод. Скажу честно: до недавнего времени LLM меня замедляли всегда, кроме случаев написания тестов и какого-нибудь жёсткого тупого копипастинга.
Но когда у Copilot появилась фича Next edit suggestions, наконец-то как будто мне стали предлагать то, что я хочу: не дополнение строчки, а автоматически изменить то, что я планирую изменить. То есть делаю рефакторинг и переименовываю какую-то вещь — copilot предлагает мне переименовать её и в других местах.
Ещё он умеет исправлять ошибки: если написать код с багом, то, по версии copilot, следующее логическое изменение — это баг исправить. Ну круто же!
Я тут нахваливаю copilot, но ещё же есть всякие windsurf'ы, continue, cursor'ы итд итп. Честно — я не в теме, и это потянет на отдельную статью. Но что мне нравится в copilot — там постоянно какая-то движуха идёт, плагин развивают, фичи появляются, и в нём есть бесплатный тариф. Как работается с другими AI-компаньонами и IDE — я не знаю, напишите, у кого какой опыт.
Для линтинга и проверки на популярные ошибки крайне рекомендую использовать ruff. Да все его, наверно, уже используют — но вдруг нет?
Важно помнить, что по умолчанию в ruff активирован только минимум правил:
[lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or McCabe complexity (`C901`) by default.
select = ["E4", "E7", "E9", "F"]
Хотите хардкорного линтинга — включайте все правила и страдайте: ruff check --select ALL
.
Не скажу, что досконально проверял эту утилиту, но тот факт, что создатели мегапопулярных ruff
и uv
пилят статический анализатор, о многом говорит. Должна получиться пушка! Пробуйте — uvx ty check
. А есть и в виде плагина для vscode.
Я не знаю, кому удобно, когда ошибки спрятаны где-то на нижней панели. У меня они показываются прямо на экране: Error lens. Это здорово, потому что позволяет сразу видеть, где что-то пошло не так:
Есть одна проблема: когда я открываю какой-то чужой проект, обычно горит ВСЁ! Но это нормально.
Если вам всё же хочется применять ruff
только к новому коду, то вам в этот issue.
Отладка, конечно, связана с логами. Но почему-то я редко вижу на проектах что-то отличное от import logging
. А зря!
Обычные логи — это мешанина текста, и все её пишут как им нравится. Структурированные логи вносят порядок: сообщение говорит о том, какое событие произошло, а атрибуты рассказывают нам о контексте этого события. На примере:
from logging import getLogger
log = getLogger(__name__)
def handle_request(request):
log.debug('Received request #%s', request.id)
if not request.user.is_authenticated:
log.debug('User %s is not authenticated, redirecting to auth page (request #%s)', request.user, request.id)
return HttpResponseRedirect(...)
...
Тут мы должны использовать ленивое форматирование ('%s', value
), повторять request.id
в двух строчках (и вообще во всех для этой функции), и важно не перепутать порядок аргументов. Сравним со структурированными логами:
from structlog import getLogger
log = getLogger(__name__)
def handle_request(request)
with bound_contextvars(request_id=request.id, user=request.user):
log.debug('request received')
if not request.user.is_authenticated:
log.debug('redirecting anonymous user')
return HttpResponseRedirect(...)
...
Во все логи будут автоматически добавлены request_id
и user
, при этом всё будет красиво выводиться на экран, и можно выводить не только как текст, но и, скажем, в формате json для дальнейшего автоматического анализа.
Есть разные библиотеки, например, loguru. Но я использую библиотеку structlog, потому что у loguru на логотипе заросший мужик, а у structlog — бобёр. Выбор как бы очевиден.
В интерпретируемых языках прикольно то, что можно запустить REPL, то есть интерактивную среду, где можно писать код и сразу видеть, как он не работает. В питоне туда можно попасть, если просто запустить python
. Но все знают: там некрасиво. Ведь REPL — это не только про запуск команд — это про вставку из буфера, написание многострочного кода, удобное автодополнение, раскрашивание синтаксиса и красивый вывод результатов. Всего этого нет в python
, но есть в ipython. Там даже ls
работает!
Как здорово, если бы всю эту красоту из ipython
можно было притащить в отладчик... А вот можно! Для этого есть ipdb.
В коде вставляем import ipdb; ipdb.set_trace()
, и когда выполнение достигнет этой строчки, мы «провалимся» в ipython
. Если лень всё время писать ipdb.set_trace()
, можно задать переменную окружения PYTHONBREAKPOINT="ipdb.set_trace"
и в коде просто писать breakpoint()
:
print('Before')
breakpoint()
print('After')
Можно настроить pytest, чтобы запускал ipdb
при исключениях:
pytest --pdb --pdbcls=IPython.terminal.debugger:Pdb -v ./test_example.py
Понимаю, что сейчас те, кто пользуется встроенным в IDE отладчиком, начнут накидывать мне. Справедливо! Но иногде мне проще поставить breakpoint()
на нужную строчку и быстро посмотреть, что там происходит, чем настраивать отладочную сессию.
Кроме того, мне нравится, что в ipython можно отладить любую функцию «на месте»: даже если не установлены брейкпоинты, я могу вызвать %debug foo(1, 2)
и провалюсь в отладку этой функции с этими аргументами. Что-то вроде pdb.runcall()
.
Зато в IDE отлаживать классно, потому что удобно — и все локальные переменные видно, и код как на ладони. Но я никогда не любил запуск отладчика в IDE, потому что там надо что-то настраивать — всякие launch.json
, в которых прописывать, что и как вызывать. Мне в принципе не лень это сделать один раз, но если я постоянно запускаю разный код разными командами и с разными аргументами, то каждый раз редактировать конфигурацию запуска мне вообще не прикольно.
Но внезапно я узнал, что можно запускать код как обычно, в терминале, а vscode подключать к этому коду в режиме отладки. Смотрите, так мы запускаем скрипт в режиме отладки, и он будет ждать, пока к нему подключится vscode:
python -m debugpy --listen 5678 --wait-for-client ./myscript.py
На стороне vscode я создаю такую конфигурацию один раз в жизни:
{
"name": "Python Debugger: Attach",
"type": "debugpy",
"request": "attach",
"connect": {
"host": "localhost",
"port": 5678
}
}
И всё, я запускаю эту конфигурацию в vscode и отлаживаю прям из IDE.
Бонус — можно заменить localhost
на что-то другое и отлаживать удалённо!
Я как-то пропустил этот момент и привык делать log.debug()
везде, где отлаживаю. А, оказывается, есть logpoints — возможность печатать что-то во время отладки, не засоряя код. Смотрите, при достижении строчки 2 будет напечатано сообщение, хотя никакого кода там нет.
Помимо обычных брейкпоинтов есть conditional breakpoints, которые прервут выполнение только при достижении какого-то условия. Но если этого вам мало, то есть triggered breakpoints, которые «выполнятся» только если «выполнился» какой-то другой брейкпоинт.
Извините :] Но это мой родимый канальчик, я стараюсь, блин, чтобы было интересно и даже полезно, так что мне не стыдно. Поэтому...
Подписывайтесь на мой канал «Блог погромиста», если вам нравятся мои тексты и не хочется пропустить новые. А ещё есть мой сайт, где собраны все мои статьи, заметки, биография, CV, пароли, анализы, девичья фамилия матери, кличка первого питомца и ключи от холодного кошелька: pogrom.dev
Отдельная благодарность — облачному провайдеру Timeweb, у которых я держу свои проекты. Дёшево и удобно.
Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале ↩
Перед оплатой в разделе «Бонусы и промокоды» в панели управления активируйте промокод и получите кэшбэк на баланс.