Использование многопроцессорной обработки внутри декоратора приводит к ошибке: не удается обработать функцию… она не найдена как

Я столкнулся с проблемой, которую не могу решить, и она связана с многопроцессорностью, и я использую ее внутри декоратора.

Когда я вызываю метод run_in_parallels с использованием многопроцессорной обработки, я получаю сообщение об ошибке:

Can't pickle : он не найден как __main __. Run_testcase

Вызов происходит внутри декоратора, затем следует вышеупомянутая проблема. На момент вызова того же метода run_in_parallels без декоратора все работает нормально.

В чем причина этой проблемы?


файл: w_PythonHelper.py

desc: Функция run_in_parallel используется для одновременного запуска нескольких процессов. Первый метод, который завершит работу, останавливает остальные.

from multiprocessing import Process,Event

class ExtProcess(Process):
    def __init__(self, event,*args,**kwargs):
        self.event=event
        Process.__init__(self,*args,**kwargs)

    def run(self):
        Process.run(self)
        self.event.set()

class PythonHelper(object):
    @staticmethod
    def run_in_parallel(*functions):
        event=Event()
        processes=dict()
        for function in functions:
            fname=function[0]
            try:fargs=function[1]
            except:fargs=list()
            try:fproc=function[2]
            except:fproc=1
            for i in range(fproc):
                process=ExtProcess(event,target=fname,args=fargs)
                process.start()
                processes[process.pid]=process
        event.wait()
        for process in processes.values():
            process.terminate()
        for process in processes.values():
            process.join()

файл: w_Recorder.py

desc: функция 'capture' используется для получения снимка экрана

from PIL import ImageGrab
import time

class Recorder(object):
    def capture(self):
        ImageGrab.grab().save("{f}.{e}".format(f=time.time(),e="png"))

файл: w_Decorators.py

desc: Выполняется параллельно заданная функция вместе с методом 'capture' класса 'Recorder'

from w_Recorder import Recorder
from w_PythonHelper import PythonHelper

def check(function):
    def wrapper(*args):
        try:
            recorder=Recorder()
            PythonHelper.run_in_parallel([function,args],[recorder.capture])
            print("success")
        except Exception as e:
            print("failure: {}".format(e))
        return function
    return wrapper

файл: w_Logger.py

desc: Основная программа (генерирует ошибку)

from w_Decorators import check
import time

class Logger(object):

    @check
    def run_testcase(self):
        # example function (runtime: 20s)
        for i in range(20):
            print("number: {}".format(i))
            time.sleep(1)

    def run_logger(self):
        self.run_testcase()


if __name__=="__main__":
    logger=Logger()
    logger.run_logger()

файл: w_Logger.py

desc: Основная программа (работает правильно)

from w_PythonHelper import PythonHelper
from w_Recorder import Recorder
import time

class Logger(object):

    def run_testcase(self):
        # example function (runtime: 20s)
        for i in range(20):
            print("number: {}".format(i))
            time.sleep(1)

    def run_logger(self):
        recorder=Recorder()
        PythonHelper.run_in_parallel([self.run_testcase],[recorder.capture])

if __name__=="__main__":
    logger=Logger()
    logger.run_logger()

В чем разница в том, что эти же методы, представленные в двух случаях, работают по-разному?


РЕДАКТИРОВАТЬ: Есть ли у кого-нибудь идея, чтобы решить эту проблему (это ошибка Python)? Если нет, может быть, кто-нибудь знает, как делать снимки экрана во время работы приложения?

На самом деле я нашел похожий вопрос: подкласс multiprocessing.Process работает в Linux, но не в Windows

Ответ: Чтобы исправить это, вы можете удалить участника процесса. , но как это сделать на моем примере.

Во время отладки ошибка возникает при вызове process.start () в run_in_parallel (* functions)


EDIT2: like ivan_pozdeev писал: Я могу использовать обертку как функцию, но не могу использовать ее как декоратор. У меня есть много функций, оформленных этим декоратором, и самый простой способ - использовать многопроцессорность внутри декоратора. Но, к сожалению, я не могу решить эту проблему. Может кто-то уже решал подобную проблему. Буду признателен за любую подсказку.

Функция run_in_parallel работает так, как я хочу. Две или более функции выполняются параллельно, и выполнение первой функции приводит к завершению второй функции. Когда я вызываю wrapper (function, * args) , тогда функции работают нормально, когда я помещаю этот механизм в декоратор, я получаю «не удается обработать функцию ... она не найдена как» ошибка.Подробности можно найти выше

My Traceback:

Traceback (most recent call last):
  File "C:\Interpreters\Python32\lib\pickle.py", line 679, in save_global
    klass = getattr(mod, name)
AttributeError: 'module' object has no attribute 'run_testcase'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\EskyTests\w_Logger.py", line 19, in 
    logger.run_logger()
  File "C:\EskyTests\w_Logger.py", line 14, in run_logger
    self.run_testcase()
  File "C:\EskyTests\w_Decorators.py", line 14, in wrapper
    PythonHelper.run_in_parallel([function,args],[recorder.capture])
  File "C:\EskyTests\w_PythonHelper.py", line 25, in run_in_parallel
    process.start()
  File "C:\Interpreters\Python32\lib\multiprocessing\process.py", line 130, in start
    self._popen = Popen(self)
  File "C:\Interpreters\Python32\lib\multiprocessing\forking.py", line 267, in __init__
    dump(process_obj, to_child, HIGHEST_PROTOCOL)
  File "C:\Interpreters\Python32\lib\multiprocessing\forking.py", line 190, in dump
    ForkingPickler(file, protocol).dump(obj)
  File "C:\Interpreters\Python32\lib\pickle.py", line 237, in dump
    self.save(obj)
  File "C:\Interpreters\Python32\lib\pickle.py", line 344, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Interpreters\Python32\lib\pickle.py", line 432, in save_reduce
    save(state)
  File "C:\Interpreters\Python32\lib\pickle.py", line 299, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Interpreters\Python32\lib\pickle.py", line 623, in save_dict
    self._batch_setitems(obj.items())
  File "C:\Interpreters\Python32\lib\pickle.py", line 656, in _batch_setitems
    save(v)
  File "C:\Interpreters\Python32\lib\pickle.py", line 299, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Interpreters\Python32\lib\pickle.py", line 683, in save_global
    (obj, module, name))
_pickle.PicklingError: Can't pickle : it's not found as __main__.run_testcase

6
задан 16 revs, 2 users 100% 23 May 2017 в 12:17
поделиться