如何在python中将文件描述符从父级传递给子级?

发布于 2024-09-04 08:14:35 字数 91 浏览 4 评论 0原文

我正在使用多处理模块,并使用池来启动多个工作人员。但是在父进程中打开的文件描述符在工作进程中被关闭。我希望他们开放..!有没有办法传递文件描述符以在父级和子级之间共享?

I am using multiprocessing module, and using pools to start multiple workers. But the file descriptors which are opened at the parent process are closed in the worker processes. I want them to be open..! Is there any way to pass file descriptors to be shared across parent and children?

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

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

发布评论

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

评论(4

苏大泽ㄣ 2024-09-11 08:14:35

在 Python 2 和 Python 3 上,multiprocessing.reduction 模块中存在用于发送和接收文件描述符的函数。

示例代码(Python 2 和 Python 3):

import multiprocessing
import os

# Before fork
child_pipe, parent_pipe = multiprocessing.Pipe(duplex=True)

child_pid = os.fork()

if child_pid:
    # Inside parent process
    import multiprocessing.reduction
    import socket
    # has socket_to_pass socket object which want to pass to the child
    socket_to_pass = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    socket_to_pass.connect("/dev/log")
    # child_pid argument to send_handle() can be arbitrary on Unix,
    # on Windows it has to be child PID
    multiprocessing.reduction.send_handle(parent_pipe, socket_to_pass.fileno(), child_pid)
    socket_to_pass.send("hello from the parent process\n".encode())
else:
    # Inside child process
    import multiprocessing.reduction
    import socket
    import os
    fd = multiprocessing.reduction.recv_handle(child_pipe)
    # rebuild the socket object from fd
    received_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
    # socket.fromfd() duplicates fd, so we can close the received one
    os.close(fd)
    # and now you can communicate using the received socket
    received_socket.send("hello from the child process\n".encode())

On Python 2 and Python 3, functions for sending and receiving file descriptors exist in multiprocessing.reduction module.

Example code (Python 2 and Python 3):

import multiprocessing
import os

# Before fork
child_pipe, parent_pipe = multiprocessing.Pipe(duplex=True)

child_pid = os.fork()

if child_pid:
    # Inside parent process
    import multiprocessing.reduction
    import socket
    # has socket_to_pass socket object which want to pass to the child
    socket_to_pass = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
    socket_to_pass.connect("/dev/log")
    # child_pid argument to send_handle() can be arbitrary on Unix,
    # on Windows it has to be child PID
    multiprocessing.reduction.send_handle(parent_pipe, socket_to_pass.fileno(), child_pid)
    socket_to_pass.send("hello from the parent process\n".encode())
else:
    # Inside child process
    import multiprocessing.reduction
    import socket
    import os
    fd = multiprocessing.reduction.recv_handle(child_pipe)
    # rebuild the socket object from fd
    received_socket = socket.fromfd(fd, socket.AF_INET, socket.SOCK_STREAM)
    # socket.fromfd() duplicates fd, so we can close the received one
    os.close(fd)
    # and now you can communicate using the received socket
    received_socket.send("hello from the child process\n".encode())
ζ澈沫 2024-09-11 08:14:35

还有一个名为 multiprocessmultiprocessing 分支,它用 dill 取代了 pickledill 可以 pickle 文件描述符,因此 multiprocess 可以轻松地在进程之间传递它们。

>>> f = open('test.txt', 'w')
>>> _ = map(f.write, 'hello world')
>>> f.close()
>>> import multiprocess as mp
>>> p = mp.Pool()
>>> f = open('test.txt', 'r')
>>> p.apply(lambda x:x, f)
'hello world'
>>> f.read()
'hello world'
>>> f.close()

There is also a fork of multiprocessing called multiprocess, which replaces pickle with dill. dill can pickle file descriptors, and thus multiprocess can easily pass them between processes.

>>> f = open('test.txt', 'w')
>>> _ = map(f.write, 'hello world')
>>> f.close()
>>> import multiprocess as mp
>>> p = mp.Pool()
>>> f = open('test.txt', 'r')
>>> p.apply(lambda x:x, f)
'hello world'
>>> f.read()
'hello world'
>>> f.close()
阿楠 2024-09-11 08:14:35

multiprocessing 本身具有用于在 Windows 和 Unix 平台上的进程之间传输文件描述符的辅助方法,这些方法支持在 multiprocessing.reduction 中通过 Unix 域套接字发送文件描述符:send_handle代码>和<代码>recv_handle。这些没有记录,但在模块的 __all__ 中,因此可以安全地假设它们是公共 API 的一部分。从消息来源来看,这些功能至少从 2.6+ 和 3.3+ 版本就已经可用。

所有平台都具有相同的接口:

  • send_handle(conn,handle,destination_pid)
  • recv_handle(conn)

其中:

  • conn(multiprocessing.Connection):连接发送文件描述符
  • handle (int):引用文件描述符/句柄的整数
  • destination_pid (int):接收文件描述符的进程的整数 pid - 目前仅在 Windows 上使用

multiprocessing itself has helper methods for transferring file descriptors between processes on Windows and Unix platforms that support sending file descriptors over Unix domain sockets in multiprocessing.reduction: send_handle and recv_handle. These are not documented but are in the module's __all__ so it may be safe to assume they are part of the public API. From the source it looks like these have been available since at least 2.6+ and 3.3+.

All platforms have the same interface:

  • send_handle(conn, handle, destination_pid)
  • recv_handle(conn)

Where:

  • conn (multiprocessing.Connection): connection over which to send the file descriptor
  • handle (int): integer referring to file descriptor/handle
  • destination_pid (int): integer pid of the process that is receiving the file descriptor - this is currently only used on Windows
蓝天 2024-09-11 08:14:35

据我所知,没有一种方法可以在进程之间共享文件描述符。
如果存在某种方法,它很可能是特定于操作系统的。

我的猜测是您需要在另一个层面上共享数据。

There isn't a way that I know of to share file descriptors between processes.
If a way exists, it is most likely OS specific.

My guess is that you need to share data on another level.

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