Encontré un problema que no puedo resolver y está asociado con el multiprocesamiento y lo uso dentro del decorador.Usar el multiprocesamiento dentro del decorador genera un error: no se puede recuperar la función ... no se encuentra como
Cuando estoy llamando al método run_in_parallels
usando multiprocesamiento que estoy consiguiendo el error:
Can't pickle <function run_testcase at 0x00000000027789C8>: it's not found as __main__.run_testcase
La llamada se lleva a cabo en el interior del decorador, a continuación, siguieron el problema antes mencionado. En el momento de llamar al mismo método run_in_parallels
sin un decorador, todos funcionan correctamente.
¿Cuál es la razón de este problema?
archivo: w_PythonHelper.py
desc: Función 'run_in_parallel' se utiliza para ejecutar varios procesos al mismo tiempo. El primer método, que finalizará la operación, detiene a los demás.
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()
archivo: w_Recorder.py
desc: función de 'captura' se utiliza para tomar una captura de pantalla
from PIL import ImageGrab
import time
class Recorder(object):
def capture(self):
ImageGrab.grab().save("{f}.{e}".format(f=time.time(),e="png"))
archivo: w_Decorators.py
desc: que corren paralelas una función dada junto con un método de la 'captura' de clase 'Grabadora'
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
archivo: w_Logger.py
desc: programa principal (genera error)
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()
archivo: w_Logger.py
desc: programa principal (trabaja corectly)
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()
¿Cuál es la diferencia de que estos mismos métodos que se presentan en los dos casos funcionan de forma diferente?
EDIT: ¿Alguien tiene una idea para resolver este problema (es este error de Python)? Si no, ¿alguien sabe una buena manera de capturar capturas de pantalla cuando la aplicación se está ejecutando?
En realidad me pareció pregunta similar: multiprocessing.Process subclass works on Linux but not Windows
La respuesta es: To fix this, you can remove the process member.
, pero ¿cómo se puede hacer esto por mi ejemplo.
Al depurar el error se produce cuando se llama a process.start()
en run_in_parallel(*functions)
Edit2: como ivan_pozdeev escribió: puedo utilizar envoltorio como una función, pero no se puede utilizar como decorador. Tengo muchas funciones decoradas por este decorador y la manera más simple es usar multiprocesamiento dentro del decorador. Pero desafortunadamente no puedo resolver este problema. Quizás alguien ya haya resuelto un problema similar. Estaría agradecido por cualquier pista.
'run_in_parallel' Funciona como yo quiero. Dos o más funciones se ejecutan en paralelo y la primera función, que se completa, fuerza la terminación de la segunda función. Cuando llamo al wrapper (función, * args) entonces las funciones funcionan bien, cuando pongo este mecanismo dentro del decorador obtengo 'no puedo saltear la función ... no se encuentra como' error. Los detalles pueden encontrarse por encima de
Mi Rastreo:
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 <module>
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 <function run_testcase at 0x00000000027725C8>: it's not found as __main__.run_testcase
Cuando estoy haciendo 'run_testcase' una función de nivel superior como mencionaste, recibo otro error:' No puedo saltear: no es el mismo objeto que __main __. Run_testcase_proc'. Desafortunadamente debe ser un método de una clase. Tengo que modificar el decorador existente para adoptar la nueva funcionalidad que se ejecutará en paralelo con 'run_testcase'. La función 'time.time()' es un problema menor y solo se usa para mantener un orden, podría ser fácilmente un número, por ejemplo 1,2,3 ... El problema principal era modificar el decorador. –
@ falek.marcin: de los documentos de multiprocesamiento: "los métodos enlazados o no unidos no se pueden usar directamente como el argumento de destino en Windows" (http://docs.python.org/dev/library/multiprocessing#windows) –
Puede haber una solución alternativa o alternativa para modificar el decorador. ¿Alguien tiene una idea de cómo resolverlo de manera diferente? –