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.