Языки6 мин чтения2026-03-06

Проверка кода Python: полный гайд для разработчика

Я помню, как в одном стартапе мы потратили две недели на дебаг production-проблемы, которая была видна статическому анализатору с первого взгляда. Просто никто

Я помню, как в одном стартапе мы потратили две недели на дебаг production-проблемы, которая была видна статическому анализатору с первого взгляда. Просто никто его не запускал. С тех пор я убеждён: проверка кода Python — это не опция, это базовая гигиена.

Python коварен. Он не скажет тебе о типе переменной до рантайма, не заметит неиспользуемый импорт, пока ты не запустишь код. Интерпретатор прощает многое, что в компилируемых языках ловится сразу. Поэтому проверка Python-кода — это то, что нужно автоматизировать на 100%.

Давай разберёмся, как это правильно делать.

Почему проверка кода в Python особенно критична

Вот честно: Python — это язык высокого доверия. Ты пишешь код, он работает. Красиво. Но в production'е начинаются сюрпризы.

Типичная ситуация: разработчик забыл про исключение, где-то опечатка в названии переменной, или функция возвращает None вместо списка. Код пройдёт через все тесты, потому что тесты не покрывают все edge-case'ы. И вот уже 3 часа ночи, а ты ловишь баг в production'е.

По моему опыту, 40% проблем, которые находит code review, — это ошибки, которые мог бы найти статический анализатор. Зачем тратить время людей?

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

Инструменты для статического анализа Python

Тут есть несколько игроков, у каждого своя фишка.

Pylint — это старенький, но серьёзный инструмент. Ловит всё: неиспользуемые переменные, отсутствующие импорты, нарушения PEP 8. Но иногда бывает шумным. На одном проекте мы отключили половину проверок, потому что они были слишком агрессивные.

pip install pylint
pylint your_module.py

Вывод будет примерно такой:

your_module.py:5:0: C0111: Missing module docstring (missing-docstring)
your_module.py:7:4: W0612: Unused variable 'x' (unused-variable)
your_module.py:10:0: C0103: Variable name "myVar" doesn't conform to snake_case naming style (invalid-name)

Flake8 — это мой фаворит для быстрой проверки. Комбинирует PyCodeStyle (проверка стиля) и PyFlakes (логические ошибки). Легче, чем Pylint, но ловит самое важное.

pip install flake8
flake8 your_module.py
your_module.py:2:1: F401 'os' imported but unused
your_module.py:5:1: E302 expected 2 blank lines, found 1
your_module.py:10:5: W503 line break before binary operator

Mypy — вот это штука. Это проверка типов. Если в коде есть type hints (подсказки типов), Mypy проверит, что ты не передаёшь строку где ожидается число.

def calculate_total(prices: list[float]) -> float:
    return sum(prices)

# Mypy заметит эту ошибку:
result = calculate_total(["10", "20"])  # Error: Argument 1 to "calculate_total" has incompatible type

Запускается просто:

pip install mypy
mypy your_module.py

Black — это форматер, не анализатор. Но по-хорошему, это must-have. Он переписывает твой код, приводя его к единому стилю. Никаких споров о том, где ставить кавычки.

pip install black
black your_module.py

На одном проекте мы добавили Black в pre-commit hook, и количество замечаний на code review упало на 30%.

Пошаговая настройка проверки кода в CI/CD

Теория — это хорошо, но нужно это завести в production. Вот как я это обычно делаю.

Шаг 1: Создаём .flake8 конфиг в корне проекта

[flake8]
max-line-length = 120
exclude = .git,__pycache__,venv,migrations
ignore = E203, W503
per-file-ignores =
    __init__.py:F401
    tests/*:F841

Здесь я говорю Flake8:

Шаг 2: Создаём pyproject.toml для остальных инструментов

[tool.black]
line-length = 120
target-version = ['py310']

[tool.mypy]
python_version = "3.10"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
ignore_missing_imports = true

[tool.isort]
profile = "black"
line_length = 120

Black и Mypy читают конфиг отсюда. Я специально не установил disallow_untyped_defs = true, потому что это слишком строго для существующих проектов.

Шаг 3: Добавляем в requirements-dev.txt

flake8==6.1.0
mypy==1.7.0
black==23.12.0
isort==5.13.2
pylint==3.0.3

Шаг 4: Создаём GitHub Actions workflow (или GitLab CI)

Если используешь GitHub:

name: Code Quality

on: [push, pull_request]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'
      
      - name: Install dependencies
        run: |
          pip install -r requirements-dev.txt
      
      - name: Run Black
        run: black --check .
      
      - name: Run isort
        run: isort --check-only .
      
      - name: Run Flake8
        run: flake8 .
      
      - name: Run Mypy
        run: mypy .

Для GitLab CI:

code_quality:
  stage: test
  image: python:3.10
  script:
    - pip install -r requirements-dev.txt
    - black --check .
    - isort --check-only .
    - flake8 .
    - mypy .
  only:
    - merge_requests

Теперь каждый PR/MR будет проверяться автоматически. Если что-то не прошло — PR не сольётся.

Частые ошибки, которые ловит анализ кода Python

Когда я запускаю Flake8 на новом проекте, обычно вижу одно и то же:

Неиспользуемые импорты

import os  # Забыли удалить
import sys
from typing import Optional

def get_config():
    return {}

Flake8 скажет: F401 'os' imported but unused. Удаляем, и всё.

Ошибки в именах переменных

def calculate_price(quantity, unitPrice):  # unitPrice нарушает PEP 8
    return quantity * unitPrice

Должно быть unit_price. Mypy и Pylint это заметят.

Отсутствующие возвращаемые значения

def process_data(data: list[dict]) -> dict:
    if not data:
        return  # Вернули None, а не dict!
    
    return {"status": "ok"}

Mypy на это возмутится.

Потенциальные баги с None

def get_user_email(user_id: int) -> str | None:
    # ...
    return user.email  # user может быть None

# Позже:
email = get_user_email(123)
email.lower()  # Может упасть, если email это None

Mypy в strict mode это поймает и заставит тебя обработать None.

Слишком сложные функции

Pylint ловит функции, которые слишком сложные (циклическая сложность > 10). Это признак того, что функцию нужно разбить.

def complex_logic(a, b, c):
    if a:
        if b:
            if c:
                # ... много кода
                if something:
                    # ... ещё много кода

Лучше разбить на несколько функций.

Динамический анализ vs статический

Тут важно понимать разницу. Статический анализ — это когда инструмент смотрит на текст кода. Динамический — это когда код запускается.

Статический анализ ловит:

Динамический анализ ловит:

Вывод: используй оба. Статический анализ — в CI/CD на каждый коммит. Динамический — это тесты (unit tests, integration tests).

На одном проекте мы писали код, который проходил все статические проверки, но на production'е валился из-за специфичного поведения базы данных. Тесты спасли нас.

Интеграция с IDE

Если ты используешь VS Code, установи расширение Python. Оно автоматически запустит Pylint/Flake8 прямо в редакторе.

Для PyCharm — встроена поддержка Pylint, PEP 8, и других инструментов. Просто включи в настройках.

Это экономит время: ты видишь ошибки сразу, ещё до того, как коммитишь.

Как не переусложнить

Важный момент: не надо включать все проверки подряд. Это приведёт к параличу разработки. На одном проекте мы включили Pylint со всеми проверками, и разработчики восстали.

Мой рецепт:

Начни с малого. Добавь Flake8 и Black в CI/CD. Дай команде привыкнуть. Потом добавь Mypy.


Если хочешь, чтобы проверка работала на 100% без ручного запуска — используй Distiq. Это AI code review, который интегрируется с GitHub, GitLab или GitVerse. Бот автоматически проверяет каждый MR/PR и оставляет комментарии с ошибками, проблемами безопасности и предложениями по оптимизации. Настраивается за 2 минуты, не требует сложной конфигурации. Работает, как команда опытных code reviewer'ов, но без их зарплаты.

Попробуйте Distiq для автоматического code review

AI-бот анализирует каждый MR/PR и оставляет комментарии с замечаниями. Интеграция за 2 минуты.

Попробовать бесплатно

Похожие статьи