我正在尝试使用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()函数中的文件描述符直接使用?更重要的是,只要我不将连接对象用于其他任何事情,这样做是否安全?
答案 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())