Я использую многопроцессорный модуль и использую пулы для запуска нескольких рабочих. Но файловые дескрипторы, открытые в родительском процессе, закрыты в рабочих процессах. Я хочу, чтобы они были открыты..! Есть ли способ передать файловые дескрипторы для совместного использования родительским и дочерним элементами?
Как передать файловые дескрипторы от родителя к дочернему в python?
Ответы (4)
Я не знаю способа поделиться файловыми дескрипторами между процессами. Если способ существует, он, скорее всего, зависит от ОС.
Я предполагаю, что вам нужно обмениваться данными на другом уровне.
multiprocessing
сам имеет функции, которые обрабатывают детали ОС, см. здесь.
- person Chris Hunt; 05.01.2019
В 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())
send_handle
и recv_handle
также существуют в Python 2, как я упоминал в своем ответе здесь, нет необходимости различать их. Кроме того, я бы не стал использовать отправку сокета в качестве примера, поскольку multiprocessing
регистрирует socket.socket
с помощью своего пользовательского Pickler - объект socket.socket
может быть отправлен через Connection
напрямую без какого-либо кода выше, но если оставить как есть, кто-то может скопировать его в свой собственная кодовая база.
- person Chris Hunt; 05.01.2019
socket.socket
без дополнительного кода, похоже, он не работает с произвольными каналами/сокетами, а только с теми, которые созданы с помощью всего механизма multiprocessing.Manager
.
- person Piotr Jurkiewicz; 05.01.2019
Существует также ответвление 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()
multiprocess
? вы работаете в Windows и у вас нет компилятора C?
- person Mike McKerns; 07.06.2018
Сам 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
): целочисленный pid процесса, который получает файловый дескриптор — в настоящее время используется только в Windows.
sys.platform
и просто вызвать специфичную для ОС функцию, чтобы она работала для этой функции ОС. Я предлагаю прочитать код многопроцессорного модуля, чтобы увидеть, есть ли простой обходной путь. - person Rakis   schedule 07.06.2010