13

在 Windows 上使用多处理似乎任何打开的文件句柄都由衍生的进程继承。这具有锁定它们的令人不快的副作用。

我对以下任一感兴趣:
1)防止继承
2)从生成的进程中释放文件的方法

考虑以下代码,它在 OSX 上运行良好,但在 os.rename 的 Windows 上崩溃

from multiprocessing import Process
import os

kFileA = "a.txt"
kFileB = "b.txt"

def emptyProcess():
    while 1:
        pass

def main():
    # Open a file and write a message
    testFile = open(kFileA, 'a')
    testFile.write("Message One\n")

    # Spawn a process
    p = Process(target=emptyProcess)
    p.start()

    # Close the file
    testFile.close()

    # This will crash
    # WindowsError: [Error 32] The process cannot access the file
    #               because it is being used by another process
    os.rename(kFileA, kFileB)

    testFile = open(kFileA, 'a')
    testFile.write("Message Two\n")
    testFile.close()

    p.terminate()


if __name__ == "__main__":
    main()
4

4 回答 4

5

fileno()方法返回运行时库分配的文件编号。给定文件编号,然后您可以调用msvcrt.get_osfhandle()以获取 Win32 文件句柄。在对 的调用中使用此句柄SetHandleInformation。所以类似下面的东西可能会起作用:

win32api.SetHandleInformation(
    msvcrt.get_osfhandle(testFile.fileno()),
    win32api.HANDLE_FLAG_INHERIT,
    0)

我不确定该win32api模块的确切用法,但这应该有助于弥合 Python 文件对象和 Win32 句柄之间的差距。

于 2009-06-11T23:05:35.887 回答
3

我不知道多处理模块,但是使用子进程模块,您可以指示它不继承任何文件描述符:

如果 close_fds 为 true,则在执行子进程之前,将关闭除 0、1 和 2 之外的所有文件描述符。(仅限 Unix)。或者,在 Windows 上,如果 close_fds 为真,则子进程将不会继承任何句柄。请注意,在 Windows 上,您不能将 close_fds 设置为 true,也不能通过设置 stdin、stdout 或 stderr 来重定向标准句柄。

或者,您可以使用os.closerange关闭子进程中的所有文件描述符

关闭从 fd_low(包括)到 fd_high(不包括)的所有文件描述符,忽略错误。可用性:Unix、Windows。

于 2009-06-04T01:41:10.920 回答
0

打开文件句柄后,可以使用 SetHandleInformation() 函数删除HANDLE_FLAG_INHERIT标志。

于 2009-06-04T01:20:52.380 回答
0

我在使用旋转日志和多处理时遇到了这个问题。当父进程尝试轮换日志时,它会失败并显示

WindowsError:[错误 32] 进程无法访问该文件,因为它正被另一个进程使用

基于其他一些答案,以下是python 2.7中的一个有效解决方案,用于防止日志文件处理程序被继承

fd = logging.getLogger().handlers[0].stream.fileno() # The log handler file descriptor
fh = msvcrt.get_osfhandle(fd) # The actual windows handler
win32api.SetHandleInformation(fh, win32con.HANDLE_FLAG_INHERIT, 0) # Disable inheritance

请注意这个问题在 python 3.4 中有所解决。有关更多信息,请参阅 https://www.python.org/dev/peps/pep-0446/

于 2016-03-30T09:04:36.297 回答