我想替换隐藏文件的内容,因此我尝试在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()
问。 w
和r+
模式之间的区别是什么,一方有“权限被拒绝”但另一方运作良好?
UPDATE:我使用Python 2.6.6在win7 x64上,目标文件的隐藏属性设置。当我尝试关闭隐藏属性时,w
模式成功。但当我重新打开它时,它再次失败。
问。为什么w
模式在隐藏文件上失败?这是已知行为吗?
答案 0 :(得分:30)
这就是Win32 API的工作原理。在幕后,Python的open
函数调用CreateFile
函数,如果失败,它会将Windows错误代码转换为Python IOError
。
r+
开放模式对应dwAccessMode
GENERIC_READ|GENERIC_WRITE
和dwCreationDisposition
OPEN_EXISTING
。 w
开放模式对应dwAccessMode
GENERIC_WRITE
和dwCreationDisposition
CREATE_ALWAYS
。
如果您仔细阅读CreateFile
文档中的评论,则说明:
如果指定了
CREATE_ALWAYS
和FILE_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}')