【问题标题】:Why isn't mmap closing associated file (getting PermissionError: [WinError 32])?为什么 mmap 不关闭关联文件(获取 PermissionError: [WinError 32])?
【发布时间】:2018-04-15 11:40:46
【问题描述】:

在尝试使用 O'Reilly 网站的 Reading Binary Data into a Mutable Buffer 部分中的一些代码时,我在末尾添加了一行以删除创建的测试文件。

但是这总是会导致以下错误:

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data'

我不理解这种行为,因为with memory_map(test_filename) as m: 应该隐式关闭关联文件,但显然没有。我可以通过保存从os.open() 返回的文件描述符,然后在with 套件中的语句块完成后使用os.close(fd) 显式关闭它来解决此问题。

这是一个错误还是我错过了什么?

代码(带有几行注释掉的行显示了我的 hacky 解决方法):

import os
import mmap

test_filename = 'data'

def memory_map(filename, access=mmap.ACCESS_WRITE):
#    global fd  # Save to allow closing.
    size = os.path.getsize(filename)
    fd = os.open(filename, os.O_RDWR)
    return mmap.mmap(fd, size, access=access)

# Create test file.
size = 1000000
with open(test_filename, 'wb') as f:
     f.seek(size - 1)
     f.write(b'\x00')

# Read and modify mmapped file in-place.
with memory_map(test_filename) as m:
    print(len(m))
    print(m[0:10])
    # Reassign a slice.
    m[0:11] = b'Hello World'

# os.close(fd)  # Explicitly close the file descriptor -- WHY?

# Verify that changes were made
print('reading back')
with open(test_filename, 'rb') as f:
     print(f.read(11))

# Delete test file.
# Causes PermissionError: [WinError 32] The process cannot access the file
# because it is being used by another process: 'data'
os.remove(test_filename)

【问题讨论】:

    标签: python windows python-3.x permissions mmap


    【解决方案1】:

    来自文档:

    关闭()

    关闭 mmap。对对象的其他方法的后续调用将导致引发 ValueError 异常。这不会关闭打开的文件。

    内存映射独立于文件句柄。您可以将文件句柄用作普通文件。

    【讨论】:

    • 好的,感谢您澄清这个问题。事后看来,现在似乎很明显。 ^_^
    • mmap 复制文件句柄,它保持打开状态以供sizeresize 方法使用。 mmap 使重复的文件句柄保持打开状态有时令人沮丧。 Windows 将允许删除只读(不可写)映射视图的底层文件——但 mmap 将关闭文件句柄以取消映射视图。
    • @eryksun:重复的文件句柄在 mmap 内部正确处理。我怀疑可以删除映射文件,因为内容是按需映射的。
    • 删除映射为只读的文件是可能的,但它需要关闭时删除打开(或等效NtDeleteFile),因为Windows文件系统只调用MmFlushImageSection和@在这种情况下使用 987654326@ 检查而不是 DeleteFile 使用的完整 MmFlushForDelete 检查(即本机 NtSetInformationFileFileDispositionInformation)。在最近的 Windows 版本中,这就是 cmd.exe 删除文件的方式,这就是我发现这一点的方式。
    • 由于resize 不适用于只读映射,保持文件句柄打开的唯一原因是size 方法,但知道底层文件大小(不是映射的size) 对于只读映射毫无用处。所以我认为最好关闭只读视图的文件句柄并在这种情况下为size() 引发异常,就像已经为resize 所做的一样——或者至少提供一个选项来关闭文件句柄。
    猜你喜欢
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 2022-06-22
    • 2021-06-10
    相关资源
    最近更新 更多