Общие ценности Python

В моем проекте у меня есть несколько таких флагов:

file_a = False
file_b = False
file_c = False

Я пытаюсь запустить два процесса: один (сейчас назовем его A) обрабатывает входящие сообщения в очереди сообщений, второй (сейчас назовем его B) обрабатывает некоторую обработку данных. B работает с булевыми флагами, а A устанавливает их значения:

def a():
    while True:
        ...
        ...
        file_a = True
        ...

def b():
    while True:
        ...
        if file_a:
            process(file_a)
            ...

a_proc = Process(target=a)
b_proc = Process(target=b)
a_proc.start()
b.proc.start()

Но значения, кажется, не меняются. Я читал, что мне следует использовать многопоточность, и, похоже, это работает, но я рекомендую использовать многопроцессорность вместо потоков.


person Amir    schedule 28.09.2015    source источник


Ответы (2)


Если вам нужно обмениваться данными между процессами с многопроцессорным модулем, вы можете напрямую разделить память:

multiprocessing.Value

Value — это оболочка вокруг объекта ctypes, которая имеет базовый атрибут value, представляющий фактический объект в памяти. Все, что делает значение, — это гарантирует, что только один процесс или поток может читать или записывать этот атрибут значения одновременно.

from multiprocessing import Value
file_a = Value('i', 0)
file_b = Value('i', 0)
file_c = Value('i', 1)

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

>>> Value('i', True)
<Synchronized wrapper for c_int(1)>
>>> Value('i', False)
<Synchronized wrapper for c_int(0)>
>>> bool(Value('i', False).value)
False
>>> bool(Value('i', 50).value)
True

Предпочтение вкуса, но, может быть, лучший вариант, вы можете использовать c_bool из ctypes:

from multiprocessing import Value
from ctypes import c_bool
file_a = Value(c_bool, False)
file_n = Value(c_bool, False)
file_c = Value(c_bool, True)

>>> Value(c_bool, False)
<Synchronized wrapper for c_bool(False)>
>>> Value(c_bool, 5)
<Synchronized wrapper for c_bool(True)>

multiprocessing.Manager словарь:

Чтобы собрать несколько логических флагов, вы можете использовать словарь, но он должен быть разделен между процессами, поэтому вам пригодится Manager().

from multiprocessing import Manager
manager = Manager()
flags = manager.dict({'file_a' : False, 'file_b' : False, 'file_c' : True})

>>> flags
<DictProxy object, typeid 'dict' at 0x7f70822f06d0>
>>> flags['file_a']
False
>>> dict(flags)
{'file_a': False, 'file_c': True, 'file_b': False}

И, наконец, собираем все вместе:

Я выберу подход Manager просто потому, что он сделает код чище:

from multiprocessing import Process, Manager
manager = Manager()

    def a():
        while True:
            ...
            ...
            flags['file_a'] = True
            ...

    def b():
        while True:
            ...
            if flags['file_a']:
                process(file_a)
                ...

    if __name__ == '__main__':
        flags = manager.dict({'file_a' : False, 'file_b' : False, 'file_c' : True})
        a_proc = Process(target=a)
        b_proc = Process(target=b)
        a_proc.start()
        b.proc.start()
person akalikin    schedule 28.09.2015
comment
Спасибо! Есть ли более простой способ? - person Amir; 28.09.2015

Ваши file_a, file_b, file_c загружаются в каждый процесс отдельно. Вам нужно использовать Value из multiprocessing

person Josh Wilters    schedule 28.09.2015
comment
Ваш ответ действительно может использовать некоторые объяснения и примеры - person akalikin; 28.09.2015
comment
@akalikin я здесь новенький. добавит комментарий - person Josh Wilters; 28.09.2015
comment
@akalikin извините, я пока не могу комментировать - person Josh Wilters; 28.09.2015
comment
Вопрос... не можете ли вы передать управляемую переменную (менеджера) (dict) каждому процессу? Process(target=a,args(flags,)) и Process(target=b,args(flags,)), таким образом, def a(flags) и def b(flags). Переменная flags не передается по ссылке, если это сделано? Теперь, когда управляемая переменная является «общедоступной», кажется, что ссылка на объект должна работать? - person Schorschi; 16.07.2021