TGViewer
Библиотека питониста | Python, Django, Flask Библиотека питониста | Python, Django, Flask @pyproglib · 37.4K subscribers
Post #7749 2.17K
➡️ Два бага из-за области видимости в Python — и как их избежать

Приложение работает нормально. Открываешь вторую вкладку — данные не те. Тесты проходят по отдельности, но падают вместе. Причина — объект на уровне модуля.

Проблема 1: слишком много sharing

Типичный паттерн в FastAPI-проектах:

# database.py
engine = create_engine("sqlite:///database.db")


engine создаётся в момент импорта. Все модули, которые импортируют из database.py, используют один и тот же engine, один пул соединений, один файл БД.

Тесты чистят базу через setup/teardown, но состояние всё равно утекает: автоинкремент ID, кэш метаданных, внутреннее состояние SQLite. Тест assert id == 1 проходит первым, но падает если запустить после другого теста.

Фикс — создавать engine на каждый тест:

@pytest.fixture
def engine():
engine = create_engine("sqlite://", echo=False)
SQLModel.metadata.create_all(engine)
yield engine
engine.dispose()

In-memory БД, никакого shared state, никакой уборки.

Проблема 2: слишком мало sharing

Обратная ситуация. Зависимость FastAPI создаёт новый экземпляр на каждый запрос:

def get_data_source() -> DataSource:
return FakeDataSource(...) # новый объект каждый раз


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

Фикс — app.state:

@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.data_source = get_data_source()
yield

def get_data_source(request: Request) -> DataSource:
return request.app.state.data_source

Один экземпляр на весь процесс, легко подменяется в тестах через dependency_overrides.

Правило одной строкой

Если объект хранит мутабельное состояние — выбирай его скоуп осознанно. Слишком широкий (модуль) — тесты текут друг в друга. Слишком узкий (каждый запрос) — нет общего состояния. Константы и чистые значения на уровне модуля — ок. Ресурсы (DB engine, HTTP клиент, кэш, пул соединений) — нет.

📍 Навигация: ВакансииЗадачиСобесы

Библиотека питониста

#буст
  • ❤ 5
  • 👍 1
  • 🤩 1
More from @pyproglib
  1. Sep 20, 2026👻 94% токенов уходят не на код Анализ запусков показал: основная часть токенов уходит на…
  2. Sep 19, 2026📚Напоминаем про наш полный курс «Самоучитель по Python для начинающих» Мы написали и собр…
  3. Sep 15, 2026😭 Как не потратить недельный лимит AI-кодинга за три дня? Разберём на вебинаре, как трати…
  4. Sep 15, 2026⏱️ Справочник по Big-O в Python Для тех, кто хочет писать не просто работающий, а эффектив…
  5. Sep 14, 2026🤪 Если бы можно было задать один вопрос про AI в разработке — что бы вы спросили? Как выб…
  6. Sep 13, 2026🌸 Вселенная намекает: пора уже начать этот курс С 14 сентября цены в Proglib Academy выра…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →