Я пытаюсь преобразовать следующий псевдо-код Python:Как избежать состояния гонки с помощью makedirs?
If <directory> does not exist: Create all subdirectories for <directory> Create a file in <directory>
Это звучит достаточно просто выполнить с os.makedirs
и os.path.isdir
:
if not os.path.isdir('/some/path'):
os.makedirs('/some/path')
open('/some/path/test.txt', 'w')
Однако при дальнейшем осмотре там явно гонки состояние подарок. Рассмотрим следующий график:
- указанный каталог (
/some/path
) не существует - интерпретатор Python выполняет первую строку, которая оценивает в
True
- другой процесс создает каталог (
/some/path
) makedirs
вызывает исключениеOSError
, поскольку каталог уже существует
re также являются проблемами, если каталог изначально существует, но удаляется другим процессом до выполнения последней строки.
Когда дело доходит до Python, «легче просить прощения, чем разрешения». Имея это в виду, фрагмент выше, может быть лучше написано:
try:
os.makedirs('/some/path')
except OSError:
pass
open('/some/path/test.txt', 'w')
Это решает две проблемы, описанные выше, но создает третий: os.makedirs
поднимает OSError
исключение, когда один из следующих условий:
- каталог уже существует
- не может быть создан каталог
Это означает, что не может определить, какое из двух условий вызвало возбуждение исключения. Другими словами, фактические провалы будут игнорироваться, и это не то, что я хочу.
Как я могу обойти эту проблему?
Хорошая идея! И я могу использовать ['errno.EEXIST'] (http://docs.python.org/2/library/errno.html#errno.EEXIST) вместо hardcoding' 17'. –
У нас все еще есть состояние гонки, правда, правильно? – seriousdev