Как пользоваться VS Code в полную силу


image


Это небольшой туториал о настройке VS Code для работы с python. Здесь вы не увидите каких-то божественных откровений — тут будет просто мой опыт о том, как сделать свою работу/хобби немного комфортнее и почему я пришел именно к такой конфигурации.


Часть первая. "Мы строили строили и наконец построили!" (с) один очень мудрый ушастый персонаж


Мой путь к разработке начался через администрирование, и, как и любой админ, я сталкивался с необходимостью писать автоматизацию. Bash/python/powershell/go — это все типичные инструменты инженера. Но в большинстве своем мы пишем автоматизацию в vim/nano/notepad++. И на все рассказы про IDE я лишь пожимал плечами — "а мне то это зачем?". Но однажды появился проект на Python, где я стал писать код уже "в промышленных масштабах"… Результат предсказуем — я пересел на VS Code.
Почему он? Да все просто:


  • Быстрый
  • Удобный
  • Бесплатный
  • Куча плагинов

Я осознал прелесть линтера (линтер (linter) — это программа, которая автоматизирует «причёсывание» кода по определённым правилам), подсказки синтаксиса, и прочие прелести современных IDE.


Но разбираться в VS Code "все еще было некогда". И в один прекрасный момент за эту лень я поплатился сполна — у меня закрылся VScode с ошибкой и при запуске у меня открылось пустое окно. Это был шок. Привычка писать в пустых файлах, кое-как настроенные параметры запуска отладки, настройки linter-а и подсказок по синтаксису — все это в полной мере дало о себе знать. И в итоге было принято решение разобраться что тут к чему и как мне сохранить свои настройки.
В итоге мое изучение VS Code разделилось на три этапа:


  1. Единые настройки на все проекты.
    С этого я начал, но очень быстро понял, что мне необходимо делать отдельные настройки для разных проектов.
  2. Отдельные настройки под каждый проект.
    Почти идеальный вариант, если бы не проблемы со сборкой некоторых специфических библиотек под MacOS.
  3. Разработка в контейнерах.
    Очень интересный вариант разработки, лично мне он показался очень удобным.

Немного о идеологии VS Code.


Из коробки VS Code можно назвать "весьма продвинутым блокнотом". В общем то так бы все и осталось, если бы не система плагинов — с их помощью можно превратить VS Code практически во что угодно.


Теперь немного теории, чтобы мы одинаково понимали используемые термины и у нас был единый контекст. Почему это в моем понимании важно? Да потому что я мучался с этим достаточно долго, пока не собрал свою порцию шишек и граблей.
Понятия:


  1. Workspace
    В VS Code очень многое крутится вокруг такого понятия как Workspace. В заложенной логике Workspace — это папка с вашим проектом, область применение настроек и параметров запуска отладки.
    Системные папки в Workspace и их назначение:
  2. .vscode
    Точка в начале — обязательна. В этой папке vscode ищет настройки окружения и запуска отладки для данного Workspace.
  3. .devcontainer
    Точка в начале — обязательна. В этой папке vscode ищет настройки контейнеров и Dockerfile для сборки для данного Workspace.

Область видимости настроек:


  1. User
    Настройки сохраняются для конкретного пользователя
  2. Workspace
    Настройки сохраняются для конкретной области

Файлы и их назначение:


  1. %name%.code-workspace
    Настройки для данного Workspace. Может содержать настройки плагинов, путей к интерпретатору и тому подобное. Удобно, можно передавать его другим.
  2. launch.json
    Настройка логики и параметров запуска отладки проекта. Может содержать несколько вариантов настройки для одного и того же проекта.
  3. settings.json
    Может содержать настройки плагинов, путей к интерпретатору и тому подобное. Переопределяет настройки из %name%.code-workspace.
  4. devcontainer.json
    Файл содержащий настройки процесса сборки контейнера и его содержимого

Что нужно для старта?


В целом все просто — надо поставить сам python, поставить нужные расширения и сделать настройки. Кажется, что все банально, но как обычно "дьявол кроется в деталях".


Настройка Python


Для того, чтобы начать разрабатывать на питоне с помощью VS Code надо сделать 3 вещи:


  1. Установить сами python (думаю с этим вы сами справитесь).
  2. Поставить набор плагинов для разработки (делается в самом VS Code, занимает минимум времени).
  3. Настроить различные дополнительные модули для более комфортной и качественной работы. Это:
    • linter (я использую flake8).
    • language server (настраивается в файле settings.json, я использую Pylance) (Вот тут неплохая статья описывающая что это и зачем это). Тут как раз обычно и скрыта вся магия.
    • параметры запуска отладки (файл launch.json). Вторая часть магии.

Плагины, необходимых для работы с python-ом:


  • Python Extension Pack (id — donjayamanne.python-extension-pack)
    В этот плагин входит все, что нужно для разработки на python
  • Dev Containers (id — ms-vscode-remote.remote-containers)
    Этот плагин нужен для работы в контейнерах

Настройка удаленной разработки


Об этом я бы хотел тоже упомянуть, так как это очень удобная история. Есть такой набор плагинов от компании Microsoft — Remote Development (id — ms-vscode-remote.vscode-remote-extensionpack). Туда входят:


  • Remote — Tunnels
    Назначение этого плагина не знаю, не разбирался
  • Dev Containers
    Этот плагин позволяет нам разрабатывать и/или отлаживать код в контейнерах. Обязателен для установки, если хотите работать в контейнерах.
  • Remote — SSH
    Этот плагин предназначен для удаленной разработки с подключением к удаленному хосту по ssh. Причем вы можете не только редактировать файлы или запускать команды, но и заниматься полноценной разработкой с отладкой и всем прочим. Проблема с сохранением файлов, на которых нет прав, может решить плагин sudo (Save as Root in Remote — SSH, id yy0931.save-as-root).
  • WSL
    Этот плагин очень поможет пользователям Windows — с его помощью можно разрабатывать в среде полноценного Linux, подключаясь к нему через WSL.

Лирическое отступление. 'Емае... Что ж я сделал то...' (с) реклама из 90-тых.

Все было очень просто, пока репозиторий был один. Кое-как я настроил какие-то совсем базовые вещи и на этом успокоился. Проблемы этого подхода всплыли тогда, когда репозиториев стало три и в одном из них использовался не python а Go. Ну и конечно же по классике — я не использовал venv =)
Вот небольшой список тех проблем, которые я испытывал постоянно:


  • Периодически отваливались импорты в python. Лечилось это переустановкой пакета и перезапуском приложения. (Да-да, это все еще было терпимо, так как происходило не часто)
  • Запуск проектов был не самым простым делом, но я как настоящий самурай написал bash-скрипты для запуска. (Чего только не сделаешь, лишь бы не читать доки)
  • Когда появился Go — на нем просто не работала отладка… В итоге отладкой я занимался в виртуалке…
    Ну и добил меня случай, который я описал выше — я профукал настройки Workspace по дефолту.
    И вот, мой дорогой читатель, сижу я перед ноутом, смотрю в пустую страницу VS Code и понимаю, что час настал...

Часть вторая. Single and multi-root workspace.


Как я уже говорил, Workspace в VS Code это по сути свое область видимости настроек. Осознав это, я с ужасом понял, что мою идеологию "одно окно — много проектов" можно похоронить. Но остатки надежды говорили, что я не один такой и возможно решение есть среди тысяч плагинов, которые есть для VS Code. Но все оказалось даже лучше, начиная с версии 1.18 этот функционал доступен из коробки. И тут у меня начал вырисовываться примерный план приведения в порядок моего рабочего места разработчика. Он был в целом прост:


  1. Сделать отдельную корневую папку для всех проектов.
  2. Каждый проект лежит в отдельной директории.
  3. Для каждого из проектов я сделаю свои отдельные настройки.
  4. Все общие настройки буду хранить в корневой общей папке.

Сказано — сделано. В итоге у меня появился такая структура каталогов:


Development
├───.vscode
│   └───my_dev_env.code-workspace
├───First project
│   ├───!env
│   │   ├───prod.env
│   │   └───dev.env
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
├───Second project
│   ├───!env
│   │   ├───prod.env
│   │   └───dev.env
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
└───Third project
    ├───!env
    │   ├───prod.env
    │   └───dev.env
    ├───.vscode
    │   ├───launch.json
    │   └───settings.json
    └───app
        ├───file111.txt
        ├───file112.txt
        └───...

Начнем по порядку:


  • Development/.vscode/my_dev_env.code-workspace.
    тут лежат пути к папкам и общие настройки для всех Workspace. В этом файле мы определяем общие настройки на все проекты. Переопределить их можно с помощью локального файла с настройками — settings.json, он будет описан ниже. Пример файла (описание всех свойств даны в самом файле):


    {
    // Список папок, которые должны попасть в вашу multi-root.
    // Пути можно использовать абсолютные, поэтому можно собирать
    // воедино папки из разных мест
    "folders": [
        {
            "path": "/Development/First project"
        },
        {
            "path": "/Development/Second project"
        },
        {
            "path": "/Development/Third project"
        }
    ],
    // Общие настройки. Они являются дефолтными для всех включенных директорий,
    // но могут переопределяться на уровне конкретной корневой папки проекта.
    // Тут собраны те, что использую я
    "settings":  {
        "git.autofetch": true,
    // Включить или выключить периодический поиск изменений в удаленном
    // репозитории. В случае, если включено в VS Code в разделе работы 
    // с git будет показывать сколько неполученных коммитов есть
    // в удаленном репозитории.
        "python.languageServer": "Pylance",
    // Выбор language server. У Python их несколько, с последнего времени
    // по дефолту используется Pylance. На мой взгляд лучше оставить его,
    // так как его делает Microsoft и он активно развивается.
        "python.defaultInterpreterPath": "/opt/homebrew/bin/python3.10",
    // Дефолтный путь для Питона
        "python.analysis.diagnosticMode": "openFilesOnly",
    // Выбор области, где производится анализ файлов на ошибки.
    // Я выбрал вариант "только открытые файлы" чтобы меньше логало
        "python.analysis.autoImportCompletions": true,
    // Включает автоматическое добавление импорта модуля, если его нет,
    // но в коде найдены на него ссылки
        "python.analysis.typeCheckingMode": "off",
    // Очень полезная, но очень суровая опция - включает проверку
    // соответствия типов для языкового движка Pylance. По сути попытка
    // сделать из Python типизированный язык. Доступные значения:
    //  off: анализ проверки типа не проводится; производится диагностика
    //       неразрешенных импортов/переменных
    //  basic: Правила, не связанные с проверкой типов (все правила в off)
    //         + базовые правила проверки типов
    //  strict: все правила проверки типов с наивысшей серьезностью ошибки
    //          (включая все правила в категориях off и basic)
    "python.analysis.inlayHints.variableTypes": true,
    // Анализирует ваши переменные и предлагает для них подходящие типы.
    // Так же позволяет двойным кликом добавить тип
    "python.analysis.inlayHints.functionReturnTypes": true,
    // Анализирует ваши функции и классы и предлагает подходящие типы
    // выходных данных. Так же дает подсказки, какой выходной тип вы получите
        "python.terminal.activateEnvironment": true,
    // Если в проекте найдено виртуальное окружение, то в терминале оно
    // будет автоматически активироваться при переходе в этот проект
        "python.linting.enabled": true,
    // Включает линтер для питона
        "python.linting.flake8Enabled": true,
    // Выбор каким линтером пользоваться.  Я выбрал flake8.
        "python.linting.flake8Args": [
            "--max-line-length=250",
    // "--ignore=E402,F841,F401,E302,E305",
        ],
    // Настройки flake8. Я лично выставил себе только увеличение максимальной
    // длинны строки - по дефолту 80, этого мало для меня
        "[python]": { 
    // Настройка автоматического форматирования. Удобно тем, что при сохранении
    // автоматически приводит форматирование к правильному по мнению форматора виду
            "editor.defaultFormatter":"ms-python.python",
    // Выбор форматера
            "editor.formatOnSave": true,
    // Включает форматирование при сохранении
            "editor.codeActionsOnSave": {
                    "source.organizeImports": true
    // Форматирует импорты. Могут быть проблемы, если импорты зависят друг от друга
            },
        "files.exclude": {
    // Крайне полезная на мой взгляд функция - задается список файлов, которые
    // исключаются из показа в дереве каталогов. Отлично подходит для скрытия всяких
    // ненужных системных каталогов
      "**/.git": true,
            "**/__pycache__": true,
            "**/.DS_Store": true,
        "**/Thumbs.db": true
    },
        "files.watcherExclude": {
    // еще одна крайне любопытная опция - за изменениями файлов из
    // этого списка VS Code не следит
            "**/.git/objects/**": true,
            "**/.git/subtree-cache/**": true,
            "**/node_modules/*/**": true,
            "**/.hg/store/**": true,
            "**/__pycache__/**": true,
            "**/.venv-*/**": true
        },
    "files.enableTrash": false,
    // Включение/выключение корзины. Если False то файлы удаляются сразу же
    "cSpell.language": "en,ru",
    // Крайне полезный плагин и настройки - проверка орфографии.
    // Настоятельно рекомендую к установке
    "cSpell.words": [
    // Тут список слов, которые мы добавили в исключения
            "Clickhouse",
            "fastapi",
            "jsonify",
            "loguru"
        ]
    }
    }

  • Далее идет папка .vscode внутри папки проекта. Тут мы видим два файла — settings.json и launch.json.
    Файл settings.json нужен для того, чтобы переопределить параметры из одноименной секции файла workspace (my_dev_env.code-workspace). Вот пример файла


    {
    "python.defaultInterpreterPath": "${workspaceFolder}/.venv-first-project/bin/python3.10",
    // Переопределяем путь к Python. Тут есть два интересных момента:
    //    1. используется переменная ${workspaceFolder} - она обозначает
    //       корневую папку проекта
    //    2. Путь указывает сразу же в каталог с виртуальным окружением
    "python.envFile": "${workspaceFolder}/!env/dev.env",
    // Крайне полезная директива - она позволяет задать переменные окружения,
    // которые будут использоваться при запуске Python. Очень помогает при отладке
    // при pytest, которым нужны переменные из окружения для работы
    }

    Файл launch.json нужен для настройки запуска отладки приложения. Оооо… Насколько же моя жизнь стала проще, когда я открыл для себя этот файл...


    {
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
    // Важно - можно делать сколько угодно наборов настроек отладки
    {
      "name": "First project - Dev",
    // Наименование набора настроек для запуска и отладки. Выводится в
    // выпадающем списке при запуске отладки. Мне нравится сюда вписывать проект
    // и окружение, в котором будет запущена отладка
      "type": "python",
    // указание какой язык используется - нужно для запуска нужного
    // набора параметров отладки
      "request": "launch",
    // Указывает режим, в котором следует начать отладку.
    //   - launch - если вы запускаете код локально
    //   - attach - если вы используете удаленную отладку
    // (но эта история более сложная, поэтому тут я ее не буду описывать)
      "program": "${file}",
    // Путь к исполняемому файлу. По умолчанию ${file} обозначает файл,
    // который выбран сейчас в активном окне. Если прописать туда какой-то
    // конкретный файл, то запускается будет всегда он, вне зависимости
    // от того, какое окно у вас сейчас выбрано.
      "console": "integratedTerminal",
    // Указатель того, куда выводить stdout и stderr.
    // По умолчанию - встроенный терминал.
    // Менять в моем понимании надо только если ты четко понимаешь что делаешь )
      "python": "${workspaceFolder}/.venv/bin/python3.10",
    // путь к интерпретатору, с помощью которого запускаться проект
      "cwd": "${workspaceFolder}",
    // Указывает каталог, из которого запускается для отладчика,
    // который является базовой папкой для любых относительных путей,
    // используемых в коде. Если опущено, по умолчанию используется ${workspaceFolder}.
      "jinja": true,
    // Активирует специфические параметры окружения для отладки шаблонов jinja
      "envFile": "${workspaceFolder}/!env/dev.env",
    // указывает на файл со списком переменных окружения.
    // Есть нюанс - на данный момент не поддерживает многострочные переменные,
    // то есть если вам нужно в окружение добавить большой json - придется
    // сначала перевести его в компактный вид (в одну строку)
      "justMyCode": true,
    // Ограничивает отладку вашим кодом. В случае, если стоит False то отладчик будет
    // показывать шаги и в стандартных библиотеках.
      "presentation": {
    // Настройки видимости этой настройки отладки в списке всех отладок
        "hidden": false,
    // Если True то эта отладка не будет видна в списках
        "group": "api",
    // Имя группы, нужно для логической группировки отладок
        "order": 1
    // Порядковый номер в группе
      },
      "autoReload": {
    // Перезапуск отладки в случае сохранения файла с новым кодом.
    // Если отладка идет в рамках активного файла - перезапустится только он.
        "enable": true
      }
    },
    // Пример настройки для запуска проекта написанного на FastApi
    {
      "name": "FastAPI",
      "type": "python",
      "request": "launch",
      "module": "uvicorn",
    // В отличие от предыдущего раза, где запускается файл из текущего активного окна,
    // тут запускается вполне конкретный модуль
      "console": "integratedTerminal",
      "envFile": "${workspaceFolder}/!env/stage.env",
    // Заведя несколько файлов с переменными окружения можно легко переключаться
    // на отладку в разных окружениях
      "python": "${workspaceFolder}/.venv/bin/python3.10",
      "cwd": "${workspaceFolder}",
      "args": [
    // параметры запуска - специфичны для FastApi
        "app.main:app",
    // в моем случае:
    //   первое app- это пака в корне файла проекта
    //   main - это название файла,
    //   второе app - это имя экземпляра класса FastAPI
    //   (выглядит как app = FastAPI())
        "--host",
        "0.0.0.0"
    // , "--workers", "5" // количество воркеров запускаемых по умолчанию.
    // Нужно для высоконагруженного продакшена
      ],
      "jinja": true,
      "justMyCode": true,
      "presentation": {
        "hidden": false,
        "group": "api",
        "order": 5
      }
    }
    ]
    }


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


Часть третья. Новые горизонты или разработка прямо в контейнере.


И вот, казалось бы, наступило счастье, благодать, бабочки порхают и в мире больше не осталось проблем… Но радость была не долгой — мне пришлось работать с MSSQL, а с драйвер упорно не хотел становиться ко мне на машину. И тут я понял, что это следующий пинок — разобраться с возможностью разработки в контейнерах.


История с разработкой в контейнерах прямо внутри VS Code витала в моей голове уже очень давно, но как обычно, волшебного пинка не было. И вот он настал...
На самом деле у VS Code есть два режима поддержки контейнеров:


  • полноценная разработка в контейнерах (будет рассматриваться в статье)
  • отладка в контейнерах (мне показалась эта история более громоздкой, поэтому не ковырял)

Теперь пара слов о том, как идеологически устроено использование контейнера в качестве полноценной среды разработки.
Логическая схема разработки в контейнере


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

Шаги, которые происходят при запуске разработки в контейнере:


  1. Мы выбираем папку, которую хотим открыть в контейнере.
  2. VS Code ищет в корне этой папки специальную директорию .devcontainer.
  3. В этой директории ищется специальный файл — devcontainer.json. Он содержит в себе информацию о том, как запустить нужный контейнер.
  4. В случае, если мы собираем контейнер сами, то запускается процесс сборки с помощью Dockerfile из этой же директории.
  5. В случае, если мы пользуемся уже собранным контейнером из заданного регестри, то скачивается указанный нами образ.
  6. После того, как контейнер запустился, стартует команда, описанная в разделе "initializeCommand" из файла devcontainer.json (если они заданы).
  7. Следующим шагом запускается установка расширений внутрь контейнера. Список расширений указывается в файле devcontainer.json.
  8. После установки расширений стартует команда, описанная в разделе "postCreateCommand" из файла devcontainer.json (если они заданы).

Вот так будет выглядеть наша структура каталогов для разработки в контейнерах:


Development
├───.vscode
│   └───my_dev_env.code-workspace
├───First project
│   ├───!env
│   │   ├───prod.env
│   │   └───dev.env
│   ├───.devcontainer
│   │   ├───devcontainer.json
│   │   └───Dockerfile
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
├───Second project
│   ├───!env
│   │   ├───prod.env
│   │   └───dev.env
│   ├───.devcontainer
│   │   ├───devcontainer.json
│   │   └───Dockerfile
│   ├───.vscode
│   │   ├───launch.json
│   │   └───settings.json
│   └───app
│       ├───file111.txt
│       ├───file112.txt
│       └───...
└───Third project
    ├───!env
    │   ├───prod.env
    │   └───dev.env
    ├───.devcontainer
    │   ├───devcontainer.json
    │   └───Dockerfile
    ├───.vscode
    │   ├───launch.json
    │   └───settings.json
    └───app
        ├───file111.txt
        ├───file112.txt
        └───...

Рассмотрим более подробно новые файлы.
devcontainer.json:


{
    "name": "docker-my_project",
// Это имя будет показываться в интерфейсе VS Code и обозначать в каком
// контейнере вы работаете
    "build": {
// Эта секция отвечает за то, как будет собираться ваш контейнер.
// Вариантов два - или собирать из Dockerfile при старте, или брать из
// какого-нибудь registry. Я пошел по первому варианту - он для меня проще
        "dockerfile": "Dockerfile",
// Это самый обычный Dockerfile для сборки образа
        "context": ".."
// Это очень важный параметр - он указывает в контексте какой директории
// собирается контейнер и относительно этой директории будут отрабатывать
// все пути в Dockerfile. В примере - это папка проекта First project.
// Соответственно, если у вас в Dockerfile написано "COPY app/requirements.txt ."
// то это значит, что при сборке каталог app будет искаться относительно папки
// First project. Эта возможность позволяет вам очень гибко собирать ваши образы.
    },
    "remoteUser": "root",
// Пользователь из-под кого запускается все в контейнере. Мне было лень
// заморачиваться и я оставил root.
// Есть еще две крайне любопытные команды - они позволяют вписать набор команд,
// выполняемых перед всеми действиями в контейнере (например, установка расширений)
// и сразу же после инициализации контейнера, перед передачей управления пользователю.
// Тут приведен пример, как можно это использовать - ставить зависимости
// или запускать сборки npm.
// "initializeCommand": "cp ../app/requirements.txt .",
// "postCreateCommand": "pip3 install -r /workspaces/alkir-infra-api/app/requirements.txt",
    "extensions": [
// тут мы задаем список расширений VS Code, которые хотим увидеть при разработке в контейнере.
// Тут приведен мой - замените на свой.
        "ms-python.python",
        "wholroyd.jinja",
        "formulahendry.code-runner",
        "streetsidesoftware.code-spell-checker",
        "VisualStudioExptTeam.vscodeintellicode",
        "VisualStudioExptTeam.intellicode-api-usage-examples",
        "humao.rest-client",
        "streetsidesoftware.code-spell-checker-russian",
        "adpyke.vscode-sql-formatter",
        "mtxr.sqltools",
        "ultram4rine.sqltools-clickhouse-driver",
        "DotJoshJohnson.xml",
        "redhat.vscode-yaml",
        "njpwerner.autodocstring"
    ],
    "customizations": {
// В этой секции вы переопределяете настройки по умолчанию.
// Логичнее всего скопировать сюда информацию из общего файла настроек.
        "vscode": {
            "settings": {
                "python.defaultInterpreterPath": "/usr/local/bin/python3.10",
                "python.linting.enabled": true,
                "sql-formatter.uppercase": true,
                "python.linting.flake8Enabled": true
            }
        }
    },
    "forwardPorts": [
// Список портов, которые будут проброшены из контейнера.
// Нужно для того, чтобы обращаться к своему приложению внутри контейнера по сети.
// Так как у меня проект FastAPI он по умолчанию открывает 8000 порт на прослушивание.
        8000
    ]
}

Пример Dockerfile для работы с Python


FROM python:3.10.8-buster as builder

COPY app/requirements.txt .

RUN set -ex \
 && apt-get update -yqq \
 && ACCEPT_EULA=Y apt-get install --no-install-recommends -yqq \
      unixodbc-dev \
      libpq-dev \
      g++ \
      git \
      rsync \
      freetds-dev \
      freetds-bin \
      tdsodbc \
 && pip3 install flake8 pylint autopep8 \
 && pip3 install -r requirements.txt

После того, как мы все настроили остается только запустить это все. Для этого надо нажать F1, и в появившейся строке ввода ввести "Open folder in container". После этого выбрать корневую папку проекта. После чего запустится сборка контейнера и папка откроется внутри контейнера.
И еще один момент. Как правильно, если вы хотите перезапустить контейнер или перестроить его у вас выпадает ошибка. Это, как правило, связано с тем, что контейнер не успевает удалиться. Попробуйте нажать retry и как правильно все срабатывает.


Так же, из неописанных возможностей (пока просто не разобрался), есть возможность стартовать зависимые контейнеры при запуске отладки. К примеру, вы разрабатывается фронт, и у вас в контейнерах стартуют бек с апи и субд для бека. Очень удобная штука.


Полезные ссылки


Тут находится официальная документация — https://code.visualstudio.com/docs/
Открытая спецификация о разработке в контейнерах — https://containers.dev/
Поддерживаемые переменные в файлах настройки — https://code.visualstudio.com/docs/editor/variables-reference
Настройки python — https://code.visualstudio.com/docs/python/settings-reference
Перечень переменных в файле отладки — https://code.visualstudio.com/docs/editor/debugging#_launchjson-attributes

Комментарии (18)


  1. kai3341
    00.00.0000 00:00
    +5

    На одном из прошлых проектов я такое видел. ИМХО подход остро конфликтует с принципом KISS и характеризуется ключевым словом `overcomplicated`

    Однако допускаю, что приму этот вариант со временем


    1. Dr_Wut Автор
      00.00.0000 00:00

      А в чем именно конфликтует если не секрет?


      1. kai3341
        00.00.0000 00:00

        А в чем именно конфликтует если не секрет?

        Ваш вопрос завёл меня в некоторый тупик. Видите ли, вот всём. И когда на серьёзных щах такой вопрос задают -- зреют встречные вопросы

        Однако mode собака-подозревака: off. Неужели всё описанное проще, чем:

        1. Запуск контейнеров через docker compose run --rm --service_ports? Смысл в том, что:

          1. Мы получаем интерактивную консоль, в которой без бубнов работает pdb

          2. Время запуска / остановки контейнера на глаз не отличается от локального запуска процесса

          Если вас пугает длинная команда и большое число аргументов -- вы же программист, не? Я алиасы в своё время создал в проекте, скрыв кучу аргументов и подковёрной дичи (если не знаете, докеры на разных платформах имеют свои нюансы), и с автодополнениями по табу

        2. Для remote pdb / rdb пробрасываем изнутри наружу одинаковые порты. Тогда они даже команду правильную пишут -- копипастим не включая мозг

        Описанное выше нахожу на порядок более простым и идентичным локальному запуску, со всеми преимуществами локального запуска и при этом всеми преимуществами докера

        Обратите внимание -- мой подход уместил в один комментарий -- настолько всё просто


        1. Dr_Wut Автор
          00.00.0000 00:00

          Ну... Читая ваш комментарий мне отчетливо вспомнился анекдот про "но только в гамаке и стоя!". Что ж - это ваш выбор.

          По поводу ваших аргументов:

          1. Когда я сосредоточен на разработке мне не очень хочется вспоминать что и как запускать, какие команды стартовать и прочее - я хочу открыть IDE и получить все плюшки сразу же, не задумываясь о том, как их в очередной раз запустить.

          2. Я могу хранить настройки проекта в гите, и он будет одинаковый везде. Если мне надо будет что-то добавить/убавить - это автоматом уедет всем разработчикам в проекте, причем самым простым для них способом - через гит

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


          1. kai3341
            00.00.0000 00:00
            +2

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

            Я про алиасы кому говорил? Про автодополнения по табу кому расписывал?

            А ещё, оказывается, у нас IDE много разных. Мой подход сожрёт любая -- универсальность вашего же меня огорчает

            Я могу хранить настройки проекта в гите, и он будет одинаковый везде.
            Если мне надо будет что-то добавить/убавить - это автоматом уедет всем
            разработчикам в проекте, причем самым простым для них способом - через
            гит

            И заведётся во всех IDE и на всех платформах. Правда, всё так. Даже не смешно кстати.

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

            Я уже не в первый раз сталкиваюсь, когда невежество возносится в благодетель. Это странная тенденция.

            Вообще при любом раскладе надо писать инструкцию. Именно длина инструкции определяет сложность того или иного подхода. Ваша заняла несколько экранов -- моя уместилась в комментарий. Уместите статью в размер комментария -- тогда я вам поверю.

            А если вы считаете что разработчики все поголовно хорошо разбираются в администрировании - то вы заблуждаетесь.

            Неужели 1 комментарий, который можно прочитать за 20 секунд -- это такая адская сложноть "администрирования" (лол. Уровень детского сада кстати). То ли дело -- 16 минут на чтение, рабочий день на настройку


            1. Dr_Wut Автор
              00.00.0000 00:00
              +1

              Хорошо, вы можете продолжать считать ваш способ верхом совершенства. Продолжайте убеждать себя в собственной крутости 3 раза на дню =)
              За сим я с вами прощаюсь, ибо быть объектом почесывания вашего ЧСВ мне неинтересно.


              1. kai3341
                00.00.0000 00:00
                +3

                Продолжайте убеждать себя в собственной крутости 3 раза на дню =)

                Мне казалось, я общаюсь с инженером, способным в объективные метрики.

                И что в итоге? Тезис о длине (следовательно, сложности) инструкции вы проигнорировали. Тезис об универсальности вы проигнорировали. Оказывается, это "объекты почёсывания ЧСВ"

                Вообще переход на личности -- верный признак неспособности оппонента вести дискуссию. За сим тоже откланиваюсь


  1. kovserg
    00.00.0000 00:00
    +4

    Можно тоже самое, но без датчиков движения мыши: vscodium.com


    1. ArkadiyShuvaev
      00.00.0000 00:00
      +1

      Вроде как телеметрию можно отключить и в VSCode? Прямо пункт меню отдельный есть. Или это не совсем то?


    1. gmelikov
      00.00.0000 00:00

      А вот есть нюансы, некоторые дополнения можно поставить только на официальной сборке vs code, например для питона - это pylance, который технически не совсем опенсорсный емнип.

      Когда-то пришлось пересесть на офиц. сборку по этой причине.


  1. a-burlakov
    00.00.0000 00:00
    +2

    А не подскажете, почему не выбрали PyCharm? Он ведь тоже:

    - Быстрый
    - Удобный
    - Бесплатный
    - Куча плагинов

    Спрашиваю, потому что сам VS Code не пробовал, руки не доходят, и пока неочевидно, почему все так его любят.


    1. SabMakc
      00.00.0000 00:00

      VS Code подкупает своей универсальностью, возможностью разработки в контейнере (или по SSH), и подкупает своей скоростью работы.

      Много лет пользовался IDEA для java, но после VS Code она кажется тормозной...
      Причем как IDE я могу сказать, что IDEA лучше - она лучше понимает контекст, у нее лучше подсказки, лучше механики рефакторинга и т.д. IDEA лучше отшлифована, если можно так сказать. Но и VS Code заметно развилась как java IDE за последний год (вернее плагин поддержки java). Так что в последнее время я предпочитаю именно VS Code как основную IDE для java.

      Если же брать другие продукты JetBrains - то не могу сказать, что VS Code в чем-либо хуже. Пробовал для Go-разработки и для Rust-разработки. Но тут я начинал с VS Code и только потом пробовал JetBrains - и мне VS Code понравилась сильно больше. Но пробовал на очень небольшой промежуток, так что не могу сказать, что мнение тут полностью объективно.


    1. sukhe
      00.00.0000 00:00

      В бесплатном PyCharm нет поддержки Django, нет поддержки удалённой отладки, нет отладки в контейнерах и, наверное, чего-то ещё. Хотя, может я ошибаюсь и плагинами это всё допиливается (давно не пробовал PyCharm, т.к. VS Code меня устраивает).

      Единственный раз, когда PyCharm (платный) был лучше чем VS Code - удалённая разработка на FreeBSD. На VS Code она на тот момент не работала (не знаю, как сейчас).


      1. a-burlakov
        00.00.0000 00:00
        +1

        Спасибо.

        К слову скажу, что платный PyCharm (в котором весьма приятная поддержка Django) очень легко сделать бесплатным через получение License for Open Source. Я вот указал там свой репозиторий с открытым кодом (нужно, чтобы был создан более чем 3 месяца назад), написал пару комментариев в заявке, и через месяц дали лицензию на год. Даже со страной врать не пришлось. :)


    1. Dr_Wut Автор
      00.00.0000 00:00

      Все просто - я же заходил не со стороны разработки, а со стороны админства. А в VS Code очень много плагинов не относящиеся к разработке - поддержка синтаксиса yaml, bash, json, nginx, ansible и куча всего другого.
      Плюс в VS Code вы не ограничены одним языком - можно разрабатывать на разных языках в одной и той же IDE.


    1. qbertych
      00.00.0000 00:00

      А вы пробовали запускать PyCharm не на топовом железе? Я как-то попробовал, не понравилось. Ни мне, ни ноуту. С VSCode таких проблем нет, он очень легкий.


  1. mgis
    00.00.0000 00:00

    Я пробовал для отладки внутри контейнеров Docker использовать Workspaces, однако не смог пофиксить видимость контейнеров внутри workspaces между собой.
    В итоге остановился на debugpy внутри контейнера. А его то уже debugger, vscode без проблес "прослушивает".
    Единственное пришлось делать отдельный конфиг docker-compose.dev.yml в котором отдельно ставится пакет debugpy.
    Ну и launch.json тоже для докера свой.

    launch.josn
    {
    
      "version": "0.2.0",
      "configurations": [
        {
          "name":"Docker celery",
          "type":"python",
          "request":"attach",
          "connect":{"host":"localhost","port":5678},
          "pathMappings":[{
            "localRoot":"${workspaceFolder}",
            "remoteRoot":"."
          }],
          "justMyCode":true},
        {
          "name":"Docker Fastapi",
          "type":"python",
          "request":"attach",
          "connect":{"host":"localhost","port":5679},
          "pathMappings":[{
            "localRoot":"${workspaceFolder}",
            "remoteRoot":"."
          }],
          "justMyCode":true},
        {
          "name": "Fast Api",
          "type": "python",
          "request": "launch",
          "program": "${workspaceFolder}/app/main.py",
          "console": "integratedTerminal",
          "envFile": "${workspaceFolder}/.env",
          "env": {
            "PYTHONPATH": "${workspaceFolder}/${pathSeparator}${env:PYTHONPATH}"
          }
        },
        {
          "name": "chek db",
          "type": "python",
          "request": "launch",
          "program": "${workspaceFolder}/app/pre_start.py",
          "console": "integratedTerminal",
          "envFile": "${workspaceFolder}/.env",
          "env": {
            "PYTHONPATH": "${workspaceFolder}/backend/${pathSeparator}${env:PYTHONPATH}"
          }
        },
        {
          "name": "init data",
          "type": "python",
          "request": "launch",
          "program": "${workspaceFolder}/app/initialiser.py",
          "console": "integratedTerminal",
          "envFile": "${workspaceFolder}/.env",
          "env": {
            "PYTHONPATH": "${workspaceFolder}/${pathSeparator}${env:PYTHONPATH}"
          }
        }
      ]
    }

    docker-file.dev.yml
    version: "3.8"
    
    services:
    
      worker:
        build:
          context: .
          dockerfile: ./Dockerfile.dev    
        env_file:
          - .env.dev     
        volumes:
          - ./:/usr/src/project          
        ports:
        - "5678:5678"
        
    
      api:
        build:
          context: .
          dockerfile: ./Dockerfile.dev
        env_file:
          - .env.dev
        volumes:
          - ./:/usr/src/project
        ports:
        - "5679:5678"        
    
      nginx-proxy:
        volumes:
          - ../nginx/data/dev.conf:/etc/nginx/conf.d/default.conf


    1. Dr_Wut Автор
      00.00.0000 00:00
      +1

      У VS Code появилась такая функциональность, как зависимые контейнеры. Я как раз планировал разобраться с этой историей и написать вторую часть статьи по этому поводу
      И большое спасибо за информацию - покопаю в эту сторону