I want to replace the contents of a hidden file, so I attempted to open it in w
mode so it would be erased/truncated:
>>> import os
>>> ini_path = '.picasa.ini'
>>> os.path.exists(ini_path)
True
>>> os.access(ini_path, os.W_OK)
True
>>> ini_handle = open(ini_path, 'w')
But this resulted in a traceback:
IOError: [Errno 13] Permission denied: '.picasa.ini'
However, I was able to achieve the intended result with r+
mode:
>>> ini_handle = open(ini_path, 'r+')
>>> ini_handle.truncate()
>>> ini_handle.write(ini_new)
>>> ini_handle.close()
Q. What is the difference between the w
and r+
modes, such that one has "permission denied" but the other works fine?
UPDATE: I am on win7 x64 using Python 2.6.6, and the target file has its hidden attribute set. When I tried turning off the hidden attribute, w
mode succeeds. But when I turn it back on, it fails again.
Q. Why does w
mode fail on hidden files? Is this known behaviour?
It's just how the Win32 API works. Under the hood, Python's open
function is calling the CreateFile
function, and if that fails, it translates the Windows error code into a Python IOError
.
The r+
open mode corresponds to a dwAccessMode
of GENERIC_READ|GENERIC_WRITE
and a dwCreationDisposition
of OPEN_EXISTING
. The w
open mode corresponds to a dwAccessMode
of GENERIC_WRITE
and a dwCreationDisposition
of CREATE_ALWAYS
.
If you carefully read the remarks in the CreateFile
documentation, it says this:
If
CREATE_ALWAYS
andFILE_ATTRIBUTE_NORMAL
are specified,CreateFile
fails and sets the last error toERROR_ACCESS_DENIED
if the file exists and has theFILE_ATTRIBUTE_HIDDEN
orFILE_ATTRIBUTE_SYSTEM
attribute. To avoid the error, specify the same attributes as the existing file.
So if you were calling CreateFile
directly from C code, the solution would be to add in FILE_ATTRIBUTE_HIDDEN
to the dwFlagsAndAttributes
parameter (instead of just FILE_ATTRIBUTE_NORMAL
). However, since there's no option in the Python API to tell it to pass in that flag, you'll just have to work around it by either using a different open mode or making the file non-hidden.