Возможно ли перебирать атрибуты объекта пространства имен?

#python #multiprocessing

#python #многопроцессорная обработка

Вопрос:

Я не смог найти никаких ответов на этот вопрос, но я думаю, что я не первый, кто задает этот вопрос. Так что, если он двойной — пожалуйста, простите меня 🙂

Этот код:

 from multiprocessing import Manager

manager = Manager()
global_vars = manager.Namespace()

global_vars.x = 0
global_vars.y = True
global_vars.z = "hello"
print(global_vars)
  

С принтами:

  Namespace(x=0, y=True, z='hello')
  

Если я использую этот объект пространства имен в другом процессе (используя многопроцессорную обработку), можно выполнять итерации по объекту пространства имен, не зная, какие переменные там находятся? Итак, что-то вроде:

 for var in global_vars:
  print(var)
  

Комментарии:

1. Может for var in vars(global_vars) быть?

2. @DeepSpace: это не работает, ни одно из значений var не является global_vars необходимым атрибутом.

Ответ №1:

Вот еще один, немного менее хакерский ответ, чем мой предыдущий (и теперь удаленный).

Как выясняется, global_vars на самом деле это экземпляр NamespaceProxy , а не Namespace экземпляр, из-за того, как multiprocessing.Manager работают s. У первого класса есть a __dict__ , в котором хранятся его атрибуты.

Это все еще хакерски, потому что он использует частный _getvalue() метод, который NamespaceProxy наследуется от его BaseProxy базового класса, чтобы получить копию значения базового Namespace объекта __dict__ . Помимо потенциальной проблемы, которая может возникнуть (т. Е. Не Быть актуальной), применяются обычные риски использования любого частного метода, такие как тот факт, что они могут измениться или даже исчезнуть в какой-то момент в будущем без предварительного уведомления, и тот факт, что их использование нарушает инкапсуляцию.

Тем не менее, заимствуя название книги по C Аллена Голуба, здесь достаточно веревки, чтобы выстрелить себе в ногу: ;¬)

 from multiprocessing import Manager


if __name__ == '__main__':

    manager = Manager()
    global_vars = manager.Namespace()
    global_vars.x = 0
    global_vars.y = True
    global_vars.z = "hello"

    for var in global_vars._getvalue().__dict__:
        print(var)
  

Выходной сигнал:

 x
y
z
  

Комментарии:

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

2. Это просто обходной путь для того факта, что multiprocessing.Manager.Namespace object не предоставляет способа сделать то, что необходимо (поэтому единственным выходом является зависимость от его текущей реализации). Возможно, вместо этого вам следует использовать a multiprocessing.Manager.dict . В любом случае, пожалуйста, подумайте о том, чтобы принять мой ответ, поскольку, как вы говорите, он работает и, что более важно, отвечает на заданный вами вопрос.

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

4. Черт возьми, если использование словарей слишком неудобно, я думаю, было бы довольно легко создать пользовательский Namespace класс, который был бы итеративным, и заставить его работать с a multiprocessing,Manager .