Как разделить массив строк в многопроцессорной обработке в Python 3.8? - PullRequest
1 голос
/ 22 марта 2020

Я экспериментирую с многопроцессорной библиотекой Python (v. 3.8) для разработки более крупной программы и пытаюсь разделить строки multiprocessing.Array между несколькими процессами, чтобы этот Array можно было обновить и прочитать каждым процессом с одинаковыми данными. Я попытался c_char_p, и он говорит, чтобы использовать byte строки. Однако для этого кода:

from multiprocessing import Process, Array
from ctypes import c_char_p

def show(a):
    print("This ran")
    print("a: ", a[:])

if __name__ == "__main__":
    array = Array(c_char_p, 1)
    array[0] = b'Hello World'
    print(array[:])
    p = Process(target=show, args=(array,))
    p.start()
    p.join()

выходные данные варьируются от этого:

[b'Hello World']
This ran
a:  [b'c']

до этого:

[b'Hello World']
This ran

но я ожидаю:

['Hello World']
This ran
['Hello World']

Полагаю, очевидным решением было бы совместное использование общего файла между каждым процессом, но я ожидаю использовать несколько массивов, и это может стать немного утомительным. Мне было интересно, что будет лучшим текущим решением для этого в Python 3.8.

Для этого кода:

from multiprocessing import Process, Array
from ctypes import c_char_p

def show(a):
    print("This ran")

    # Decode the encoded values
    arr = [s.decode("utf-8") for s in a]
    print(arr)

if __name__ == "__main__":
    array = Array(c_char_p, 1)
    message = b"Hello, world"
    array[0] = message

    p = Process(target=show, args=(array,))
    p.start()
    p.join()

    # Decode the encoded values
    arr = [s.decode("utf-8") for s in array]
    print(arr)

оно никогда не заканчивается (т.е. никогда не попадает в оператор печати после процесса запускается), вывод:

This ran

Я не уверен, почему.

Ответы [ 2 ]

1 голос
/ 22 марта 2020

Я не думаю, что предполагается для работы в целом.

По сути, c_char_p - это указатель, число, которое ссылается на область памяти в процессе. И вы не можете ожидать, что указатели будут переносимыми между процессами.

Поскольку Python Process -es наследуют от своих родительских процессов, может работать для строк, которые были созданный до запуска дочернего процесса.

Но вы не можете ожидать создания новой строки в дочернем процессе, добавить указатель на массив и ожидать, что он будет действительным в родительском процессе. (И наоборот).

Использование Pipe или Queue, вероятно, является лучшим способом обмена строковыми данными.

Редактировать 1:

Используйте Pipe для отправки мутаций списка строк, например, в виде кортежа (3, "new value"). Это будет означать, что позиция 3 в списке теперь становится "new value". Использование дуплекса Pipe означает, что оба конца канала могут читать и применять каждое входящее сообщение.

Редактировать 2 :

Другой вариант - использовать a multiprocessing.Manager. Это позволит вам поделиться list с и dict с.

1 голос
/ 22 марта 2020

Значения хранятся в array в виде кодированных строк (байтовые значения) , поэтому, если вы хотите, чтобы строковые значения были декодировать их.

Попробуйте это:

from multiprocessing import Process, Array
from ctypes import c_char_p

def show(a):
    print("This ran")

    # Decode the encoded values
    arr = [s.decode("utf-8") for s in a]
    print(arr)

if __name__ == "__main__":
    array = Array(c_char_p, 1)
    array[0] = b"Hello, world"

    # Decode the encoded values
    arr = [s.decode("utf-8") for s in array]
    print(arr)

    p = Process(target=show, args=(array,))
    p.start()
    p.join()

Вывод:

['Hello, world']
This ran
['Hello, world']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...