KarolBorkowski
KarolBorkowski

Reputation: 145

@pyqtSlot() causes that a wrong handler method is called, when used with another decorator

My question is related to my previous one from this topic: Decorator adds an unexpected argument

The problem is that if I create more methods with the same set of decorator, every signal calls the same one, what is kind of weird. Example below:

signal_1.connect(fun_1)
signal_2.connect(fun_2)

@pyqtSlot()
@handle_exceptions
def fun_1():
    print('aaaaa')

@pyqtSlot()
@handle_exceptions
def fun_2():
    print('bbbbb')

signal_1.emit()
signal_2.emit()

Output:

aaaaa
aaaaa

Upvotes: 1

Views: 128

Answers (2)

musicamante
musicamante

Reputation: 48399

When the decorator is created, it receives the function as parameter, and PyQt uses the name of that function as a "pointer" to the actual function that will be used for the slot, unless a specific name is given, then it actually returns a "wrapper" to that function.

Since you're using the slot decorator against the same wrapper (func_wrapper), PyQt "thinks" they are the same function, and overwrites the previous one (or ignores the next, I'm not sure: I've got different results, as sometimes the first function is called, others the second one).

This is related to what eyllanesc explains in his answer, which I believe is the more correct approach.

Nonetheless, an alternate solution could be to set unique names as arguments for the slot:

    @pyqtSlot(name='fun_1')
    @handle_exceptions
    def fun_1():
        print('aaaaa')

    @pyqtSlot(name='fun_2')
    @handle_exceptions
    def fun_2():
        print('bbbbb')

Upvotes: 1

eyllanesc
eyllanesc

Reputation: 244162

You have to use @functools.wraps (for more information about the need read the answer of What does functools.wraps do?)

import functools

def handle_exceptions(func):
    @functools.wraps(func)
    def func_wrapper(*args, **kwargs):
        try:
            print(args)
            return func(*args, **kwargs)
        except Exception as e:
            print(e)
            return None
    return func_wrapper

Upvotes: 3

Related Questions