Skip to main content

跨 POSIX 和 Windows 系统的文件处理更加一致

项目描述

温南

  1. (动词) 斗争, 受苦, 抗争

https://en.wiktionary.org/wiki/winnan

因为在 Windows 上管理文件的一切都很糟糕。

安装

$ python -m pip install --upgrade winnan

用法

使用winnan.open()函数就像使用Python 的内置open()函数一样。它旨在成为一个替代品。

import winnan

with winnan.open("myfile") as fileobj:
    pass

返回的文件对象底层的文件描述符在 POSIX 和 Windows 系统上都具有以下两个属性 :

  1. 文件描述符是不可继承的。

  2. 当文件描述符仍然打开时,可以安排删除文件。

    说“计划删除”而不是“已删除”是对文件如何在 Windows 上进入“删除挂起”状态直到最后一个文件句柄关闭的迂腐。请参阅 Mercurial 的开发人员文档,作为文件处于“删除挂起”状态时对文件进行某些操作的语义的参考。

动机

毫不奇怪,管理文件的复杂性涉及处理其他进程。根据 Python 应用程序正在做什么,可能不仅需要处理 Python 应用程序产生的进程,还需要处理机器上运行的其他进程。

  1. 正如PEP-446所记录的,在生成子进程的同时打开文件可能会导致文件描述符被无意继承。

    该进程无法访问该文件,因为它正被另一个进程使用。

    可能是这个问题在 Windows 上最经典的表现形式。在现代版本的 Python 中,在 Windows 上打开文件描述符时,默认设置O_NOINHERIT标志。在打开的文件描述符上设置它可以防止它被子进程继承。在 POSIX 系统上打开文件描述符时,现代版本的 Python 中也会默认设置等效的O_CLOEXEC标志。

    值得一提的是,由于在旧版本的 Python 中 重定向stdinstdoutstderr时能够设置close_fds=True的限制,设置O_NOINHERIT标志不足以防止文件描述符在同时产生子进程时被泄露。考虑使用 threading.Lock实例保护对subprocess.Popen的所有调用,以避免在旧版本的 Python 中这是一个额外的问题。

  2. 在 POSIX 系统上,可以在文件仍在另一个线程或进程中打开时unlink()文件。在 Windows 上,在所有版本的 Python 中,非O_TEMPORARY文件都使用 FILE_SHARE_READ |打开。FILE_SHARE_WRITE作为他们的共享模式。省略FILE_SHARE_DELETE 可防止另一个线程或进程在文件仍处于打开状态时尝试删除它。

这个库的目的是掩盖不同平台和旧版本 Python 中的这些行为差异。

参考

已经多次尝试解决 CPython 本身中的FILE_SHARE_DELETE问题,但不幸的是它们从未成功集成。

  • bpo-12939tempfile.NamedTemporaryFile在 Windows 上不是特别有用

  • bpo-14243:支持在 Windows 上使用FILE_SHARE_DELETE打开文件

  • bpo-15244 :使用本机 Windows API添加新的io.FileIO

从 Python 3.7 开始,即使在重定向stdinstdoutstderr时也可以设置close_fds=True

  • bpo-19575进程:在 Windows 上,不需要的文件句柄由多线程应用程序中的子进程继承

  • bpo-19764进程:在 Windows Vista 上使用PROC_THREAD_ATTRIBUTE_HANDLE_LISTSTARTUPINFOEX

  • bpo-33369:在 Windows 上删除线程中的Popen日志文件很有趣

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

winnan-0.1.0.tar.gz (50.4 kB 查看哈希

已上传 source