PySide2: Cómo hacer una ranura decorada ejecutar en su subproceso de trabajo?

Derren:

Al utilizar Python 3.7 y PySide2, creé un objeto trabajador en un QThread dedicado para ejecutar una función de larga duración. Esto se ilustra en el código de abajo.

import threading
from time import sleep
from PySide2.QtCore import QObject, QThread, Signal, Slot
from PySide2.QtWidgets import QApplication

class Main(QObject):   
    signal_for_function = Signal()

    def __init__(self):
        print('The main thread is "%s"' % threading.current_thread().name)
        super().__init__()
        self.thread = QThread(self)
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.thread.start()
        self.signal_for_function.connect(self.worker.some_function)

def some_decorator(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

class Worker(QObject):
    # @some_decorator
    def some_function(self):
        print('some_function is running on thread "%s"' % threading.current_thread().name)

app = QApplication()
m = Main()
m.signal_for_function.emit()

sleep(0.100)
m.thread.quit()
m.thread.wait()

Si uso some_function sin el decorador, me sale esto como se esperaba:

The main thread is "MainThread"
some_function is running on thread "Dummy-1"

Sin embargo, si aplico un decorador (es decir uncomment "@some_decorator"), me sale:

The main thread is "MainThread"
some_function is running on thread "MainThread"

¿Por qué sucede esto, y como creo la carrera función decorada en el subproceso de trabajo, ya que a intented?

eyllanesc:

Solución:

Debe utilizar @functools.wrap:

import functools
# ...

def some_decorator(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

Salida:

The main thread is "MainThread"
some_function is running on thread "Dummy-1"

Explicación:

Para analizar la diferencia de utilizar @functools.wrapo no, entonces el siguiente código, debe usarse:

def some_decorator(func):
    print(func.__name__, func.__module__, func.__doc__, func.__dict__)

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs) 
    print(wrapper.__name__, wrapper.__module__, wrapper.__doc__, wrapper.__dict__)
    return wrapper

Mediante la eliminación @functools.wrapdebe obtener la siguiente:

some_function __main__ None {}
wrapper __main__ None {}

No eliminando @functools.wrapdebe obtener la siguiente:

some_function __main__ None {}
some_function __main__ None {'__wrapped__': <function Worker.some_function at 0x7f610d926a60>}

La diferencia principal está en __name__, en el caso de @ functools.wrap que hace la función de contenedor tiene el mismo nombre que "Func", y qué diferencia hace eso? Sirve para identificar si la función pertenece a la clase trabajador o no, es decir, cuando se crea la clase Trabajador, se crea un diccionario que almacena los métodos, atributos, etc., pero cuando los invoca señal some_function entonces se devuelve el envoltorio que tiene el nombre de "contenedor" que no está en el diccionario del trabajador, pero en el caso de utilizar @ some_function functools.wrapper se invoca a continuación, vuelve a derivador con el nombre "some_function" haciendo que el objeto del trabajador para invocarlo.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=351819&siteId=1
Recomendado
Clasificación