我正在使用multiprocessing模块,并使用池来启动多个工作进程。但是在工作进程中关闭了在父进程中打开的文件描述符。我希望它们保持打开状态..!是否有办法传递文件描述符以在父进程和子进程之间共享?
我正在使用multiprocessing模块,并使用池来启动多个工作进程。但是在工作进程中关闭了在父进程中打开的文件描述符。我希望它们保持打开状态..!是否有办法传递文件描述符以在父进程和子进程之间共享?
在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())
send_handle
和recv_handle
在Python 2中也存在,正如我在这里中提到的那样,没有必要区分两者。此外,我不会使用发送套接字作为示例,因为multiprocessing
使用其自定义Pickler注册了socket.socket
- socket.socket
对象可以直接通过Connection
发送,而无需上面的任何代码,但如果保留原样,则可能会有人将其复制到自己的代码库中。 - Chris Huntsocket.socket
而没有额外的代码,在任意管道/套接字上似乎不起作用,只适用于使用整个 multiprocessing.Manager
机制创建的那些。 - Piotr Jurkiewicz还有一个名为multiprocess
的multiprocessing
分支,它使用dill
替换了pickle
。因为dill
可以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()
multiprocess
安装有问题?你是在 Windows 上,没有 C 编译器吗? - Mike McKernsmultiprocessing
本身有助手方法,用于在支持通过Unix域套接字发送文件描述符的Windows和Unix平台之间传输文件描述符:multiprocessing.reduction
: 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上使用据我所知,没有一种方法可以在进程之间共享文件描述符。如果存在一种方法,那么它很可能是特定于操作系统的。
我猜你需要在另一个层面上共享数据。
sys.platform
来区分两者,并调用特定于操作系统的“让其针对该操作系统运行”的函数。建议阅读多进程模块的代码,以查看是否有简单的解决方法。 - Rakis