在Windows上用Python解决虚假OSError 13 (EACCES)的好方法是什么

4 投票
3 回答
2782 浏览
提问于 2025-04-16 09:28

这里是代码:

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没有抛出异常,所以在makedirs调用中出现的任何EACCESS (13)错误可能都是假的。我的尝试(根据Apalala的评论进行修改):

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

在你之前的帖子中,你提到程序出现了一个“WindowsError”错误:

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

你的代码可以通过“except”语句来处理“OSError”错误,但它无法处理“WindowsError”错误……如果你想处理“WindowsError”错误,你必须像这样使用“except”语句:

        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

难道你不能直接用一个“except”语句吗?

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

我也遇到过同样的问题,这个看起来和我的解决办法差不多,只不过我用的是睡眠(0.1)。

撰写回答