防止多处理库中的文件句柄继承

发布于 2024-07-23 14:18:33 字数 910 浏览 3 评论 0原文

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

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

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

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()

Using multiprocessing on windows it appears that any open file handles are inherited by spawned processes. This has the unpleasant side effect of locking them.

I'm interested in either:
1) Preventing the inheritance
2) A way to release the file from the spawned process

Consider the following code which works fine on OSX, but crashes on windows at os.rename

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()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

奢欲 2024-07-30 14:18:34

使用 os.set_inheritable 检查这个 了解更多详情

use os.set_inheritable check this for more details

剩余の解释 2024-07-30 14:18:34

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

After you open a file handle, you can use the SetHandleInformation() function to remove the HANDLE_FLAG_INHERIT flag.

私藏温柔 2024-07-30 14:18:34

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

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

WindowsError: [Error 32] 该进程无法访问该文件,因为根据其他一些答案,

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 2.7 中的一个工作解决方案,用于防止继承日志文件处理程序请注意此问题是python 3.4 中的一些地址。 欲了解更多信息,请参阅
https://www.python.org/dev/peps/pep-0446/

I have encountered this issue when using a rotating log and multiprocessing. When the parent process tries to rotate the log, it fails with a

WindowsError: [Error 32] The process cannot access the file because it is being used by another process

based on some of the other answers, the following is a working solution in python 2.7 to prevent log file handlers from been inherited

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

Please note this issue was somewhat address in python 3.4. for more info see
https://www.python.org/dev/peps/pep-0446/

滥情空心 2024-07-30 14:18:34

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

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

或者,您可以使用 os.closerange

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

I don't know about the multiprocessing module, but with the subprocess module you can instruct it to not inherit any file descriptors:

If close_fds is true, all file descriptors except 0, 1 and 2 will be closed before the child process is executed. (Unix only). Or, on Windows, if close_fds is true then no handles will be inherited by the child process. Note that on Windows, you cannot set close_fds to true and also redirect the standard handles by setting stdin, stdout or stderr.

Alternatively you could close all file descriptors in your child process with os.closerange

Close all file descriptors from fd_low (inclusive) to fd_high (exclusive), ignoring errors. Availability: Unix, Windows.

叫嚣ゝ 2024-07-30 14:18:33

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

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

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

The fileno() method returns the file number as assigned by the runtime library. Given the file number, you can then call msvcrt.get_osfhandle() to get the Win32 file handle. Use this handle in the call to SetHandleInformation. So something like the following may work:

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

I'm not certain of the exact usage of the win32api module, but this should help bridge the gap between a Python file object and a Win32 handle.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文