Python 使用open()打开文件时使用的共享模式

Python 使用open()打开文件时使用的共享模式,python,windows,Python,Windows,我在open()函数的参数中看不到允许指定文件共享方式的任何内容。因此,我怀疑该文件将尽可能被允许共享。具体而言: 打开文件进行读取时,其共享模式将允许后续打开操作打开文件进行读取,但不允许进行写入 打开文件进行写入时,其共享模式将拒绝后续打开文件进行读取或写入的操作 在我看来,这是最符合逻辑的实现。我的假设正确吗 更新:Martijn Pieters表示答案取决于操作系统。因此,为了回答这个问题,我的目标操作系统是Windows 打开文件进行写入时,其共享模式将拒绝后续打开文件进行读取或写入的

我在
open()
函数的参数中看不到允许指定文件共享方式的任何内容。因此,我怀疑该文件将尽可能被允许共享。具体而言:

  • 打开文件进行读取时,其共享模式将允许后续打开操作打开文件进行读取,但不允许进行写入
  • 打开文件进行写入时,其共享模式将拒绝后续打开文件进行读取或写入的操作
  • 在我看来,这是最符合逻辑的实现。我的假设正确吗

    更新:Martijn Pieters表示答案取决于操作系统。因此,为了回答这个问题,我的目标操作系统是Windows

    打开文件进行写入时,其共享模式将拒绝后续打开文件进行读取或写入的操作

    错。没有获得锁。您可以从两个不同的cmd窗口进行尝试:

    首先

    python -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)
    Python在内部使用(Python2
    open()
    函数)或(Python3和
    io.open()
    ),两者都不允许指定任何共享标志。因此,共享被设置为默认值,默认值似乎没有被记录

    如果您想自己设置共享模式,如果您想打开指定共享模式的文件,则必须使用

    有一个实现
    共享
    模块的示例,演示了如何执行此操作。该补丁的开场白稍微简化了一些,如下所示:

    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)
    

    这完全取决于操作系统;你有什么想法吗?@MartijnPieters我的目标操作系统是Windows。在Linux上,没有锁定,所以你可以打开阅读和写入任意次数。我不会将此作为回答,因为您说您正在使用Windows。相关:好的,但您知道最终传递给
    CreateFile
    的是什么吗?是不是无论Python文件模式如何,它都是
    文件共享
    读取
    ?未设置
    文件共享
    标志。完全
    open()。如果未设置
    文件共享
    标志,则以独占方式打开文件。这一切是否归结为一个事实,即底层CRT对共享一无所知?我的问题真的是关于
    \u wfopen()
    的问题吗?我想是的。顺便说一句,
    io.open()
    使用,并且这两个文档都对设置的共享模式保持沉默。很难相信Python不支持锁定和共享。