Выберите функцию для многопроцессорной обработки, перезагрузив ее - PullRequest
0 голосов
/ 06 мая 2020

Предположим, у меня есть следующий простой класс:

class HelloWorld:
   def call(self):
       print('Hello World!')

Тогда я могу использовать HelloWorld.call с многопроцессорной обработкой, хотя python знает, как мариновать HelloWorld.call. Однако, скажем, я хочу обернуть эту функцию в метакласс,

class MetaClass(type):
    def __new__(mcs, name, bases, dct):

        def wrap(f):
            def wrapper(self):
                print(f.__qualname__)
                f(self)

            return wrapper

        new_dct = dict()
        for attr_name in dct.keys():
            if callable(dct[attr_name]):
                new_dct[attr_name] = wrap(dct[attr_name])
            else:
                new_dct[attr_name] = dct[attr_name]

        return type.__new__(mcs, name, bases, new_dct)

class HelloWorld(metaclass=MetaClass):
   def call(self):
       print('Hello World!')

Тогда я не могу использовать HelloWorld.call с многопроцессорной обработкой, так как он не будет мариноваться. Я хочу, чтобы python не использовал функцию-оболочку для травления, а использовал исходную функцию (хотя после извлечения она по умолчанию будет ссылаться на упакованную функцию).

Есть предложения? Спасибо!

1 Ответ

0 голосов
/ 06 мая 2020

Глядя на исходный код, вы можете увидеть, что ForkingPickler (multiprocessing * пользовательский Pickler) солится методом __func__ -attribute's __name__. Поэтому мне нужно было установить wrapper.__name__ таким же, как исходное имя члена:

class MetaClass(type):
    def __new__(mcs, name, bases, dct):

        def wrap(f):
            def wrapper(self):
                print(f.__qualname__)
                f(self)

            #############################
            wrapper.__name__ = f.__name__
            #############################

            return wrapper

        new_dct = dict()
        for attr_name in dct.keys():
            if callable(dct[attr_name]):
                new_dct[attr_name] = wrap(dct[attr_name])
            else:
                new_dct[attr_name] = dct[attr_name]

        return type.__new__(mcs, name, bases, new_dct)

class HelloWorld(metaclass=MetaClass):
   def call(self):
       print('Hello World!')

Можно также использовать functools.update_wrapper(wrapper, f) вместо того, чтобы просто устанавливать __name__. Тоже будет работать.

...