IOError:[Errno 13]尝试以“w”模式打开隐藏文件时权限被拒绝

时间:2012-11-04 03:08:59

标签: python windows winapi file-io hidden-files

我想替换隐藏文件的内容,因此我尝试在w模式下打开它,以便将其删除/截断:

>>> 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')

但这导致了追溯:

IOError: [Errno 13] Permission denied: '.picasa.ini'

但是,我能够以r+模式实现预期结果:

>>> ini_handle = open(ini_path, 'r+')
>>> ini_handle.truncate()
>>> ini_handle.write(ini_new)
>>> ini_handle.close()

问。 wr+模式之间的区别是什么,一方有“权限被拒绝”但另一方运作良好?

UPDATE:我使用Python 2.6.6在win7 x64上,目标文件的隐藏属性设置。当我尝试关闭隐藏属性时,w模式成功。但当我重新打开它时,它再次失败。

问。为什么w模式在隐藏文件上失败?这是已知行为吗?

3 个答案:

答案 0 :(得分:30)

这就是Win32 API的工作原理。在幕后,Python的open函数调用CreateFile函数,如果失败,它会将Windows错误代码转换为Python IOError

r+开放模式对应dwAccessMode GENERIC_READ|GENERIC_WRITEdwCreationDisposition OPEN_EXISTINGw开放模式对应dwAccessMode GENERIC_WRITEdwCreationDisposition CREATE_ALWAYS

如果您仔细阅读CreateFile文档中的评论,则说明:

  

如果指定了CREATE_ALWAYSFILE_ATTRIBUTE_NORMAL,则CreateFile会失败并将最后一个错误设置为ERROR_ACCESS_DENIED,如果该文件存在且具有FILE_ATTRIBUTE_HIDDEN或{{ 1}}属性。要避免错误,请指定与现有文件相同的属性。

因此,如果您直接从C代码调用FILE_ATTRIBUTE_SYSTEM,解决方案是将CreateFile添加到FILE_ATTRIBUTE_HIDDEN参数(而不仅仅是dwFlagsAndAttributes)。但是,由于Python API中没有选项可以告诉它传递该标志,因此您只需使用不同的打开模式或使文件不隐藏即可解决它。

答案 1 :(得分:4)

以下是详细的差异: -

  

``r''打开文本文件进行阅读。流位于            文件的开头。

     ``r +''开放阅读和写作。流定位于   该            文件的开头。

     

``w''将文件截断为零长度或创建用于写入的文本文件。            流位于文件的开头。

     ``w +''开放阅读和写作。如果是,则创建该文件   不            存在,否则被截断。流定位于            文件的开头。

     

``a''开放写作。如果文件不存在,则创建该文件。   该            stream位于文件的末尾。随后的写作            到文件总是会在当前文件末尾结束,            无论是否有任何干预(3)或类似的。

     

``a +''开放阅读和写作。如果是,则创建该文件   不            存在。流位于文件的末尾。 Subse-            对文件的quent写入总是以当前的当前结束            文件结束,不论任何介入的fseek(3)或类似内容。

来自python文档 - http://docs.python.org/2/tutorial/inputoutput.html#reading-and-writing-files:-

  

在Windows上,附加到模式的'b'以二进制模式打开文件,所以   还有'rb','wb'和'r + b'等模式。 Windows上的Python   区分文本和二进制文件;行尾   文本文件中的字符会在数据时自动更改   被读或写。这种对文件数据的幕后修改   适用于ASCII文本文件,但它会破坏这样的二进制数据   在JPEG或EXE文件中。阅读时要非常小心使用二进制模式   并写这样的文件。在Unix上,附加'b'并没有什么坏处   模式,所以你可以平台独立使用它为所有二进制文件   文件。

因此,如果您使用的是w模式,那么您实际上是在尝试创建一个文件,而您可能没有权限这样做。 r+是合适的选择。

如果您处于一种您还不知道.picasi.ini存在与否的情况,并且您的Windows用户在该目录中具有文件创建权限,并且您想要添加新信息而不是从头开始该文件(又名“追加”),然后a+将是合适的选择。

它与您的文件是否隐藏无关。

答案 2 :(得分:0)

感谢这个主题;我今天有同样的问题。我的解决方法如下。适用于Python 3.7

import os

GuiPanelDefaultsFileName = 'panelDefaults.json'
GuiPanelValues = {
    '-FileName-'      : os.getcwd() + '\\_AcMovement.xlsx',
    '-DraftEmail-'    : True,
    '-MonthComboBox-' : 'Jun',
    '-YearComboBox-'  : '2020'
}

# Unhide the file via OS
if os.path.isfile(GuiPanelDefaultsFileName):
    os.system(f'attrib -h {GuiPanelDefaultsFileName}')

# Write dict values to json
with open(GuiPanelDefaultsFileName, 'w') as fp:
    json.dump(GuiPanelValues, fp, indent=4)

# Make it hidden again
os.system(f'attrib +h {GuiPanelDefaultsFileName}')