在Python多处理中共享文件描述符

时间:2014-12-23 18:20:51

标签: python-3.x multiprocessing python-multiprocessing

我正在尝试使用Pythons多处理模块来生成服务器以接收UDP消息,稍微修改它们,并将它们传递给使用子进程模块启动的grep进程。由于Popen子进程的stdin接受文件描述符,所以我想传递它。

我遇到的问题是获取一个文件描述符,该描述符与我可以传递给grep子进程的服务器进程通信。我以前使用普通的os.fork()和os.pipe()完成了这个,但我想现在使用spawn start方法进行多处理。我尝试从os.pipe中获取写入描述符,使其可继承,并通过multiprocess.Process将其作为参数传递给新进程。当我尝试使用os.fdopen(fd,' wb')在其他进程中打开它时,我得到一个错误文件描述符的OSError。这是我测试的代码的剪辑。

def _listen_syslog(ip_address, port, write_pipe):
    f = os.fdopen(write_pipe, 'wb')
    #do stuff like write to the file



def listen_syslog(ip_address, port):
    r, w = os.pipe()
    os.set_inheritable(w, True)
    proc = mp.Process(target=_listen_syslog, args=(ip_address, port, w))
    proc.start()
    #this process doesn't need to write, so close it
    os.close(w)
    #this is the descriptor I want to pass to a grep subprocess stdin
    #a similar scenario has worked before using os.fork()
    return r

最后,如果使用通过os.pipe()创建的管道无法做到这一点,我可以使用multiprocessing.Pipe(),并使用连接对象fileno()函数中的文件描述符直接使用?更重要的是,只要我不将连接对象用于其他任何事情,这样做是否安全?

1 个答案:

答案 0 :(得分:2)

我找到了解决方案。我还没弄清楚如何使用os.pipe(),但如果我使用multiprocessing.Pipe(),我可以通过调用它们的fileno()函数来使用每个连接对象的文件描述符。我发现的另一件事是,如果你想在不再引用连接对象之后使用文件描述符,你必须在每个文件描述符上调用os.dup(),否则它们将关闭,你将得到一个错误的文件描述符错误当连接对象被垃圾收集时。

import multiprocessing as mp

def _listen_syslog(ip_address, port, write_pipe):
    f = os.fdopen(write_pipe.fileno(), 'wb')
    #do stuff


def listen_syslog(ip_address, port):
    r, w = mp.Pipe(False)
    proc = mp.Process(target=_listen_syslog, args=(ip_address, port, w))
    proc.start()
    return os.dup(r.fileno())