Как передать файловые дескрипторы от родителя к потомку в Python? - PullRequest
5 голосов
/ 07 июня 2010

Я использую многопроцессорный модуль и использую пулы для запуска нескольких рабочих.Но файловые дескрипторы, которые открываются в родительском процессе, закрываются в рабочих процессах.Я хочу, чтобы они были открыты ..!Есть ли способ передать файловые дескрипторы для совместного использования родителям и детям?

Ответы [ 4 ]

7 голосов
/ 31 декабря 2014

В 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())
2 голосов
/ 07 июня 2010

Я не знаю, каким образом можно делиться файловыми дескрипторами между процессами. Если способ существует, он, скорее всего, зависит от ОС.

Полагаю, вам нужно обмениваться данными на другом уровне.

1 голос
/ 02 апреля 2016

Существует также вилка multiprocessing, называемая multiprocess, которая заменяет pickle на dill.dill может выбирать файловые дескрипторы, и, таким образом, 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()
0 голосов
/ 05 января 2019

multiprocessing сам имеет вспомогательные методы для передачи файловых дескрипторов между процессами на платформах Windows и Unix, которые поддерживают отправку файловых дескрипторов через доменные сокеты 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): целочисленный идентификатор процесса, который получает дескриптор файла - в настоящее время он используется только в Windows
...