28

我想替换隐藏文件的内容,所以我尝试以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()

Q.w和模式有什么区别r+,一个有“权限被拒绝”但另一个工作正常?

更新:我在使用 Python 2.6.6 的 win7 x64 上,并且目标文件具有其隐藏属性集。当我尝试关闭隐藏属性时,w模式成功。但是当我重新打开它时,它又失败了。

:为什么w隐藏文件模式会失败?这是已知的行为吗?

4

3 回答 3

38

这就是 Win32 API 的工作方式。在底层,Python 的open函数正在调用该CreateFile函数,如果调用失败,它会将 Windows 错误代码转换为 Python IOError.

r+打开模式对应于 a ofdwAccessModeGENERIC_READ|GENERIC_WRITEa dwCreationDispositionof OPEN_EXISTINGw打开模式对应于 a ofdwAccessModeGENERIC_WRITEa dwCreationDispositionof CREATE_ALWAYS

如果您仔细阅读CreateFile文档中的注释,它会说:

如果指定了CREATE_ALWAYSand ,则失败并将最后一个错误设置为如果文件存在并且具有or属性。为避免该错误,请指定与现有文件相同的属性。FILE_ATTRIBUTE_NORMALCreateFileERROR_ACCESS_DENIEDFILE_ATTRIBUTE_HIDDENFILE_ATTRIBUTE_SYSTEM

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

于 2012-11-04T04:11:03.947 回答
4

以下是详细的区别:-

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

``r+'' 为读写打开。流位于文件的开头。

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

``w+'' 为读写而打开。如果文件不存在,则创建该文件,否则将其截断。流位于文件的开头。

``a'' 开放写。如果文件不存在,则创建该文件。流位于文件的末尾。对文件的后续写入将始终在文件的当前末尾结束,而与任何干预 fseek(3) 或类似内容无关。

``a+'' 为读写打开。如果文件不存在,则创建该文件。流位于文件的末尾。对文件的后续写入将始终在文件的当前末尾结束,而与任何干预 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+将是合适的选择。

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

于 2012-11-04T03:14:33.177 回答
1

感谢这个线程;我今天有同样的问题。我的解决方法如下。适用于 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}')
于 2020-09-02T02:33:14.527 回答