Os.getcwd() вызывает исключение на сервере django dev

У меня есть проект django, запущенный в docker, и сервис работает с командой python manage.py runserver, с открытой автозагрузкой файлов и использованием потоков.

Мой код вызывает shutil.make_archive(), который затем вызывает os.getcwd(), и время от времени os.getcwd() вызывает FileNotFoundError, при поиске дополнительной информации, теперь я понял, что ошибка может быть вызвана тем, что путь больше не существует, потому что путь удаляется где-то еще после того, как я ввожу путь.

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

Когда все идет правильно, os.getcwd() вернет путь к корневому dir моего проекта django. И я на 100% уверен, что мой код не делает ничего связанного с манипуляциями с dir, как os.chdir().

В двух словах, сервер django работает нормально, вдруг os.getcwd() начинает выдавать ошибку, пока я не перезапущу процесс.

Мой вопрос в том, что может быть основной причиной? Возможно ли, что python manage.py runserver может вызвать какую-либо проблему?

Python: v3.8.6
Django: v3.2
Docker: v20.10.12

Оказалось, что это не имеет никакого отношения к dev-серверу или docker. Это происходит потому, что shutil.make_archive не является потокобезопасным.

Что делает shutil.make_archive:

  1. вызов os.getcwd() для сохранения текущего пути к dir
  2. os.chdir в любой нужный ему каталог
  3. выполнить процесс архивирования
  4. os.chdir обратно в каталог, сохраненный на первом этапе (аналогично выполнению pushd .; popd;)

Я вызываю shutil.make_archive одновременно из нескольких потоков, а также rmdir этих temp dirs, и поскольку os.chdir вступает в силу в зависимости от процесса, то все происходит в следующем порядке:

  1. os.chdir(dir_path)
  2. os.rmdir(dir_path)
  3. os.getcwd()

и на последнем шаге FileNotFoundError поднимается благодаря условию гонки.

Для тех, кто хочет больше узнать о потокобезопасности shutil.make_archive, есть thread, посвященный этому.

Вернуться на верх