我在open()
函数的参数中没有看到任何允许指定文件共享方式的内容。因此,我怀疑文件将尽可能地被共享。具体来说:
- 当文件用于读取时,其共享模式将允许后续的打开操作以读取文件,但不允许写入。
- 当文件用于写入时,其共享模式将拒绝后续的打开操作以读取或写入文件。
这对我来说似乎是最合理的实现。我的假设正确吗?
更新:Martijn Pieters表示答案取决于操作系统。因此,就此问题而言,我的目标操作系统是Windows。
我在open()
函数的参数中没有看到任何允许指定文件共享方式的内容。因此,我怀疑文件将尽可能地被共享。具体来说:
这对我来说似乎是最合理的实现。我的假设正确吗?
更新:Martijn Pieters表示答案取决于操作系统。因此,就此问题而言,我的目标操作系统是Windows。
_wfopen()
(Python 2 中使用 open()
函数) 或 _wopen()
(Python 3 和 io.open()
),两者都不允许指定任何共享标志。因此,共享被设置为默认值,而这个默认值似乎没有被记录在文档中。msvcrt.open_osfhandle()
来打开文件并指定共享模式。sharing
模块,演示了如何做到这一点。这个补丁中的 opener 稍微简化后是:import os
import msvcrt
import _winapi
CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
FILE_SHARE_VALID_FLAGS = 0x00000007
FILE_ATTRIBUTE_READONLY = 0x00000001
FILE_ATTRIBUTE_NORMAL = 0x00000080
FILE_ATTRIBUTE_TEMPORARY = 0x00000100
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
FILE_FLAG_RANDOM_ACCESS = 0x10000000
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
DELETE = 0x00010000
NULL = 0
_ACCESS_MASK = os.O_RDONLY | os.O_WRONLY | os.O_RDWR
_ACCESS_MAP = {os.O_RDONLY : GENERIC_READ,
os.O_WRONLY : GENERIC_WRITE,
os.O_RDWR : GENERIC_READ | GENERIC_WRITE}
_CREATE_MASK = os.O_CREAT | os.O_EXCL | os.O_TRUNC
_CREATE_MAP = {0 : OPEN_EXISTING,
os.O_EXCL : OPEN_EXISTING,
os.O_CREAT : OPEN_ALWAYS,
os.O_CREAT | os.O_EXCL : CREATE_NEW,
os.O_CREAT | os.O_TRUNC | os.O_EXCL : CREATE_NEW,
os.O_TRUNC : TRUNCATE_EXISTING,
os.O_TRUNC | os.O_EXCL : TRUNCATE_EXISTING,
os.O_CREAT | os.O_TRUNC : CREATE_ALWAYS}
def os_open(file, flags, mode=0o777,
*, share_flags=FILE_SHARE_VALID_FLAGS):
'''
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)
CreateFile
的是什么吗?无论 Python 文件模式如何,它都是 FILE_SHARE_READ | FILE_SHARE_WRITE
吗? - David Heffernanopen()
命令吗?没有设置任何FILE_SHARE
标志。实际上,open()
命令使用了_wfopen()
C API调用。 - Martijn PietersFILE_SHARE
标志,则文件会被独占打开。这是否归结于底层CRT不知道共享的事实?因此,我的问题实际上是关于_wfopen()
的问题吗? - David Heffernan_wfopen()
和 _wopen()
方法可能根据所选模式设置默认共享模式。然而,并没有记录下默认值是什么。 - Martijn Pieterspython -c "import time; f = open('tst','wb'); f.write('1'); time.sleep(3); f.write('333'); f.close"
其次,在第一个任务运行时
python -c "with open('tst','wb') as f: f.write('22')"
tst
文件中的结果为1333
。在第一个脚本的第一次写入后使用f.flush()
刷新写操作会得到2333
。丢失的数据将被替换为\x00
字符,您可以通过将第一个f.write('1')
替换为f.write('1'*10**6)
来检查。