Python многопроцессорная труба recv () doc неясно или я что-то пропустил? - PullRequest
5 голосов
/ 21 декабря 2011

Недавно я научился использовать модуль многопроцессорной обработки Python и читал официальный документ. В 16.6.1.2. Обмен объектами между процессами . Существует простой пример использования канала для обмена данными.

А, в 16.6.2.4. Объекты соединения , есть это утверждение, заключенное в кавычки "Повышает EOFError , если не осталось ничего для получения, а другой конец был закрыт".

Итак, я пересмотрел пример, как показано ниже. ИМХО, это должно вызвать исключение EOFError : ничего не отправлено, а отправляющий конец закрыт.

Пересмотренный код:

from multiprocessing import Process, Pipe

def f(conn):
    #conn.send([42, None, 'hello'])
    conn.close()

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    #print parent_conn.recv()   # prints "[42, None, 'hello']"
    try:
        print parent_conn.recv()
    except EOFError:
        pass
    p.join()

Но, когда я попробовал пересмотренный пример на моем компьютере с Ubuntu 11.04, Python 2.7.2, сценарий завис.

Если кто-нибудь может указать мне, что я пропустил, я был бы очень признателен.

1 Ответ

9 голосов
/ 21 декабря 2011

Когда вы запускаете новый процесс с mp.Process, дочерний процесс наследует каналы родительского процесса.Когда дочерний объект закрывает conn, родительский процесс все еще имеет открытый child_conn, поэтому счетчик ссылок для дескриптора файла канала все еще больше 0, поэтому EOFError не вызывается.

Чтобы получить EOFError, закройте конец канала в родительском и дочернем процессах:

import multiprocessing as mp

def foo_pipe(conn):
    conn.close()

def pipe():
    conn = mp.Pipe()
    parent_conn, child_conn = conn
    proc = mp.Process(target = foo_pipe, args = (child_conn, ))
    proc.start()
    child_conn.close()  # <-- Close the child_conn end in the main process too.
    try:
        print(parent_conn.recv())
    except EOFError as err:
        print('Got here')
    proc.join()

if __name__=='__main__':
    pipe()
...