5.5 KiB
Типичные ошибки и как их избежать
Сборник реальных проблем, с которыми сталкиваются студенты на этом курсе. Прочитайте перед началом работы — сэкономит часы отладки.
1. multiprocessing на Windows: BrokenProcessPool / бесконечный цикл
Симптом: при запуске кода с Pool или Process на Windows процесс
перезапускается бесконечно или падает с ошибкой пиккелинга.
Причина: Windows использует метод запуска spawn — каждый дочерний
процесс заново импортирует ваш модуль. Если создание воркеров не защищено,
оно повторяется в каждом импорте.
Лечение: весь код создания процессов — только под
if __name__ == "__main__":. Это правило №1 курса.
def main():
with Pool(4) as pool:
...
if __name__ == "__main__":
main()
2. «Мой параллельный код медленнее последовательного»
Причины по частоте:
- Накладные расходы (запуск процесса ~10–100 мс, передача данных через pickle) больше, чем выгода, — работа слишком мелкая.
- GIL: потоки на CPU-bound задаче не ускоряют, а только добавляют переключения.
- Слишком много частей: 10 000 задач по 1 мс — плохо; 4–8 частей по 100 мс — хорошо.
Что делать: это не ошибка, а результат для анализа. Опишите его в отчёте — именно это и является целью курса.
3. Результат параллельного запуска не совпадает с последовательным
Причины:
- результат зависит от порядка сборки частичных результатов;
- несколько воркеров изменяют общую структуру без синхронизации (гонка);
- случайные данные без фиксированного seed.
Лечение: в этом курсе все задачи устроены так, что checksum не зависит от разбиения. Если не совпадает — ищите гонку или неверную сборку.
4. Дедлок в producer–consumer
Симптом: программа висит и не завершается.
Частые причины:
- потребитель ждёт
queue.get()в бесконечном цикле, а производитель уже закончил — используйтеqueue.put(None)как «маркер конца» илиqueue.close()+join_thread(); pool.apply()без закрытия пула;- ожидание события, которое никто не установит.
Отладка: добавьте print перед/после каждого get/put — сразу видно, кто кого не дождался.
5. asyncio.run() нельзя вложить
Симптом: RuntimeError: asyncio.run() cannot be called from a running event loop.
Причина: попытка запустить event loop внутри уже работающего (например, из Jupyter).
Лечение: один asyncio.run(main()) на программу, вызывается из обычного
синхронного кода.
6. Забыли await
Симптом: RuntimeWarning: coroutine ... was never awaited, код
выполняется мгновенно и ничего не делает.
Причина: вызов корутины без await создаёт объект корутины, но не
запускает её.
Лечение: await корутина() — всегда.
7. Кириллица «кракозябрами» в консоли Windows
chcp 65001
или запуск через python -X utf8 файл.py. В VS Code терминал обычно уже UTF-8.
8. pytest не находит модуль студента
Причина: тесты запускаются не из корня курса, или solution.py лежит не там.
Лечение: запускать python -m pytest tests/ -k labXX строго из корня
курса; solution.py — в папке своей лабораторной.
9. Замеры «прыгают»
- закройте браузер/IDE-мессенджеры на время замеров;
- на ноутбуке подключите питание (троттлинг на батарее режет частоту вдвое);
- берите лучшее время из ≥3 повторов (
time_call); - не замеряйте в отладчике.
10. Списывание
Код проверяется и на совпадение между собой, и на понимание при защите.
Варианты у всех разные (см. common/варианты.md) — чужой вариант виден сразу.