Я столкнулся с проблемой, которую не могу решить, и она связана с многопроцессорностью, и я использую ее внутри декоратора.
Когда я вызываю метод run_in_parallels
с использованием многопроцессорной обработки, я получаю сообщение об ошибке:
Can't pickle
Вызов происходит внутри декоратора, затем следует вышеупомянутая проблема. На момент вызова того же метода 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