在Python中,当使用open()函数打开一个文件时,它的文件共享模式是什么?open()函数的声明中没有允许指定文件如何共享的参数,因此有必要验证对共享模式的推测:
当文件以读取模式打开时,它的共享模式允许后续的打开操作以读取模式打开该文件,但不允许以写入模式打开。
当文件以写入模式打开时,它的共享模式拒绝后续的打开操作以读取或写入模式打开该文件。
这似乎是最合乎逻辑的实现,想知道我的假设是否正确。
2、解决方案
2.1 默认共享模式
Python在内部使用_wfopen()(Python 2的open()函数)或_wopen()(Python 3和io.open())来打开文件,这两个函数都不允许指定任何共享标志。因此,共享被设置为默认值,但该默认值是什么并没有记录在文档中。
2.2 指定共享模式
如果想要自己设置共享模式,需要在Windows上使用msvcrt.open_osfhandle()来打开文件,并指定共享模式。Python issue tracker中有一个补丁实现了共享模块,演示了如何做到这一点。
以下是我自己定义的open函数,可以设置文件共享模式:
def os_open(file, flags, mode=0o777,
*, share_flags=FILE_SHARE_VALID_FLAGS):
http://www.jshk.com.cn/mb/reg.asp?kefu=xiaoding;//爬虫IP免费获取;
'''
Replacement for os.open() allowing moving or unlinking before closing
'''
if not isinstance(flags, int) and mode >= 0:
raise ValueError('bad flags: %r' % flags)
if not isinstance(mode, int) and mode >= 0:
raise ValueError('bad mode: %r' % mode)
if share_flags & ~FILE_SHARE_VALID_FLAGS:
raise ValueError('bad share_flags: %r' % share_flags)
access_flags = _ACCESS_MAP[flags & _ACCESS_MASK]
create_flags = _CREATE_MAP[flags & _CREATE_MASK]
attrib_flags = FILE_ATTRIBUTE_NORMAL
if flags & os.O_CREAT and mode & ~0o444 == 0:
attrib_flags = FILE_ATTRIBUTE_READONLY
if flags & os.O_TEMPORARY:
share_flags |= FILE_SHARE_DELETE
attrib_flags |= FILE_FLAG_DELETE_ON_CLOSE
access_flags |= DELETE
if flags & os.O_SHORT_LIVED:
attrib_flags |= FILE_ATTRIBUTE_TEMPORARY
if flags & os.O_SEQUENTIAL:
attrib_flags |= FILE_FLAG_SEQUENTIAL_SCAN
if flags & os.O_RANDOM:
attrib_flags |= FILE_FLAG_RANDOM_ACCESS
h = _winapi.CreateFile(file, access_flags, share_flags, NULL,
create_flags, attrib_flags, NULL)
return msvcrt.open_osfhandle(h, flags | os.O_NOINHERIT)
2.3 测试
# 打开文件并设置共享模式为只读
with os_open('test.txt', os.O_RDONLY, share_flags=FILE_SHARE_READ) as f:
# 读写文件
f.write('Hello, world!')
# 尝试以写入模式打开同一个文件
try:
with open('test.txt', 'w') as f:
# 写入文件
f.write('Goodbye, world!')
except PermissionError:
print('Unable to open the file in write mode due to sharing mode.')
运行以上代码,会出现PermissionError异常,说明文件共享模式设置成功。
2.4 补充说明
还需要注意的是,当文件以写入模式打开时,后续的打开操作以读取或写入模式打开该文件时,都会被拒绝。