2014-12-23 1 views
0

Я пытаюсь использовать модуль многопроцессорности Pythons, чтобы создать сервер для получения сообщений UDP, немного их модифицировать и передать их процессу grep, запущенному с модулем подпроцесса. Поскольку stdin для подпроцесса Popen принимает файловый дескриптор, я бы хотел его передать.Совместное использование файловых дескрипторов в многопроцессорной обработке Python

Проблема, с которой я столкнулась, - это получить дескриптор файла, который связывается с процессом сервера, который я могу передать в подпроцесс grep. Я делал это в прошлом, используя простые os.fork() и os.pipe(), но сейчас я хотел бы использовать многопроцессорность с методом запуска появления. Я попытался взять дескриптор записи из 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

Я нашел решение. Я не понял, как использовать 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())