Getting TypeError: <lambda>() missing 1 required positional argument: 'checked'

Hi, Martin!

I purchased your book a couple of months ago. It helps me a lot.
I’m currently developing my own application, where I try to implement the ‘Open recent files’ functionality in the main menu. It’s quite similar to your example here:


with the difference that I connect the ‘triggered’ signals to the QActions (the list of files, generated in the loop).
But neither my nor your code works for me.

Both

button.clicked.connect(lambda checked, a=a: self.button_clicked(a)) # [in your ‘signals_extra_3.py’ script]

and

new_act.triggered.connect(lambda checked, filename=file: self.OpenRecent(filename)) # [in my code]

give out the TypeError: () missing 1 required positional argument: ‘checked’.
I use PySide2 and Python 3.8

Thanks.

Hi @Gdaliy_Garmiza welcome to the forum! Glad you’re finding the book useful.

Yep, this unfortunately due to differences in how the .triggered() and .clicked() signals work between version of PyQt5 (& PySide2). The “checked” parameter is (according to the documentation) supposed to be sent with the .triggered signal, for example, but it isn’t

Can you check if this also happens when connecting to a real method (vs. a lambda)? I wonder if that has something to do with it.

If you don’t need the checked parameter (i.e. the action or button is not toggleable) you can just remove that parameter from your receiver method/function.

Hi, @martin!

Thanks for your quick response.
I seem to have tried almost all the combinations with no success.

E.g.:

#  self.OpenRecentList — list of the full filenames/paths

for file in self.OpenRecentList:
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(lambda filename=file: self.OpenRecent(filename))

def OpenRecent(self, file):

# Code that opens a file

Result: When triggering the created actions(menu items) it tries to pass the boolean instead of the filename, because the error “File False not found” is raised within my app. It seems to be the boolean from the ‘checked’ parameter which is sent from the triggered signal, but omitted in my code.

for file in self.OpenRecentList:
    def open_recent_connector(filename=file):
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result: the same as above.

for file in self.OpenRecentList:
    def open_recent_connector(checked, filename=file):
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result (on triggering the action): TypeError: open_recent_connector() missing 1 required positional argument: ‘checked’.

for file in self.OpenRecentList:
    filename = file
    def open_recent_connector():
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result (on triggering the action): the OpenRecent function is called (it opens the file), but the ‘loop problem’, described in your book, occurs. It passes the value of the last iteration when any QAction is triggered, and my app always opens the last file in the list.

Trying to fix it using your ‘naming method’ I went even as far as that:

new_act = []
for ind, file in enumerate(self.OpenRecentList):
    def open_recent_connector():
        filename = self.OpenRecentList[ind]
        return self.OpenRecent(filename)
    new_act.append(QAction(file, self))
    self.menuOpen_Recent.addAction(new_act[ind])
    new_act[ind].triggered.connect(open_recent_connector)  

Result (on triggering the action): the same as above (the loop problem).

Hey, @martin

I have found the correct solution how to do this without lambda here:
https://stackoverflow.com/questions/52283469/using-qsignalmapper

Here is the code which worked for me:

from functools import partial

def open_recent_menu_builder(self):
     for file in self.OpenRecentList:
          new_act = QAction(file, self)
          self.menuOpen_Recent.addAction(new_act)
          new_act.triggered.connect(partial(self.OpenRecent, file))

def OpenRecent(self, file):

# Code that opens a file