Что такое хорошее решение для фиктивной OSError, 13 (EACCES) с использованием Python в Windows - PullRequest
4 голосов
/ 06 января 2011

Вот код:

def make_dir(dir_name):
 if os.path.exists(dir_name):
  shutil.rmtree(dir_name)
 try:
  os.makedirs(dir_name)
 except OSError, e:
  print "ErrorNo: %s (%s)" % (e.errno, errno.errorcode[e.errno])
  raise

Если каталог уже существует, я получаю следующее:

ErrorNo: 13 (EACCES)
Traceback (most recent call last):
  File "run_pnoise.py", line 167, in <module>
    make_dir("prep_dat")
  File "run_pnoise.py", line 88, in make_dir
    os.makedirs(dir_name)
  File "c:\Program Files (x86)\Python27\lib\os.py", line 157, in makedirs
    mkdir(name, mode)
WindowsError: [Error 5] Access is denied: 'prep_dat'

Если я снова запускаю программу, она работает, указывая, что программа действительно имеет доступ к каталогу (ам), поскольку вызов shutil.rmtree, очевидно, работает. Я нашел обходной путь, который я опубликую. Однако есть ли лучшее объяснение и / или обходной путь?

Я предполагаю, что вызов shutil.rmtree возвращается до того, как ОС полностью завершит удаление всех файлов и подкаталогов. Кроме того, поскольку вызов shutil.rmtree не вызывает исключение, любая ошибка EACCESS (13) в вызове makedirs, вероятно, является поддельной. Моя попытка (измененная после комментария Апалалы):

def make_dir(dir_name):
    retry = True
    if os.path.exists(dir_name):
        shutil.rmtree(dir_name)
    while retry:
        try:
            # per Apalala, sleeping before the makedirs() eliminates the exception!
            time.sleep(0.001)
            os.makedirs(dir_name)
        except OSError, e:
            #time.sleep(0.001) # moved to before the makedirs() call 
            #print "ErrorNo: %s (%s)" % (e.errno, errno.errorcode[e.errno])
            if e.errno != 13: # eaccess
                raise
        else:
            retry = False

Кажется, это работает надежно. Существует проблема расы, упомянутая в других постах, однако она кажется маловероятной и, вероятно, приведет к другому исключению.

Ответы [ 3 ]

0 голосов
/ 06 января 2011

Разве вы не можете просто использовать выражение «кроме»?

def make_dir(dir_name):
    retry = True
    if os.path.exists(dir_name):
        shutil.rmtree(dir_name)
    while retry:
        try:
            os.makedirs(dir_name)
        except OSError, e:
            time.sleep(0.001)
            if e.errno != 13: # eaccess
                raise
        except WindowsError:
#           (do some stuff)
        else:
            retry = False

Это должно работать, нет?!

0 голосов
/ 12 января 2011

В своем предыдущем посте вы сказали, что программа вызвала исключение «WindowsError»:

WindowsError: [Error 5] Access is denied: 'prep_dat'

Ваш код может обрабатывать исключения «OSError» с помощью оператора «кроме», но не может обрабатывать «WindowsError»исключения ... если вы хотите обработать исключения «WindowsError», вы должны использовать выражение «кроме», например:

        except WindowsError:
#           (do some stuff)

Обратите внимание, что вы можете обработать любое исключение, подобное этому:

except Exception, e:
    # this code will catch all raised exceptions. The variable «e» contains an instance of the raised exception.
0 голосов
/ 06 января 2011

У меня была такая же проблема, и это похоже на мое решение, за исключением того, что я спал (0.1).

...