コードは次のとおりです。
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呼び出しが明らかに動作しているため、プログラムが実際にディレクトリにアクセスできることを示しています。投稿する回避策を考え出しました。しかし、より良い説明や回避策はありますか?
私の想定では、OSがすべてのファイルとサブディレクトリの削除を完全に完了する前に、shutil.rmtree呼び出しが返されます。また、shutil.rmtree呼び出しは例外をスローしないため、makedirs呼び出しでのEACCESS(13)エラーは偽物である可能性があります。私の試み(アパラーラのコメントの後に修正された):
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
これは確実に機能するようです。他の投稿で言及されている競合状態の問題がありますが、それはありそうもないようで、おそらく別の例外が発生するでしょう。