4

I made a minimal pynput program that does different actions when the left and right arrow keys are pressed. I want to turn this into a function that can take different values as arguments.

Here is a minimal working example without a function, and without arguments:

from pynput.keyboard import Key, Listener 

def on_press(key):
    print('{0} pressed'.format(key))

    if key == Key.esc:
        return False
with Listener(on_press=on_press) as listener:
    listener.join()

It prints the key you press, and quits when you press esc.

And here is what I am trying to implement. Note that it doesn't work. Just look at the logic. When left arrow is pressed, I want the program to execute a command that depends on a given argument. And vice versa for the right arrow.

from pynput.keyboard import Key, Listener

def on_press(key, left, right):
    if key == Key.left:
        print("{}'s key was pressed.".format(left))
    if key == Key.right:
        print("{}'s key was pressed.".format(right))

    if key == Key.esc:
        return False

def activate(name1, name2):
    with Listener(
            on_press=on_press(key, left=name1, right=name2)) as listener:
        listener.join()
        # when pressed, the program should print what on_press() is given as argument 

activate('Mark', 'John')
Nicolas Gervais
  • 33,817
  • 13
  • 115
  • 143
  • Does this answer your question? [how to leverage python closure to write callback functions](https://stackoverflow.com/questions/54505851/how-to-leverage-python-closure-to-write-callback-functions) – Davis Herring Jan 18 '20 at 21:06
  • not even close. – Nicolas Gervais Jan 19 '20 at 00:35
  • How is it not? The way you “pass arguments” to a function that is *actually* being called by some other code is to make it a closure (or a bound method, especially if you have several different functions to which you wish to “pass” the same arguments). – Davis Herring Jan 19 '20 at 00:50
  • I don't understand the question/answer, and it contains no explanation at all. i have nothing to work with – Nicolas Gervais Jan 19 '20 at 15:10
  • To be fair, that question is asking about a harder case—where you want the callback function to be *stateful*. But the basic idea is just the same: define a function (with `def` or `lambda`) *inside* `activate` and pass it (without calling it, as always) to `Listener`. – Davis Herring Jan 19 '20 at 22:04
  • Those concepts are very new to me. Why not just answer my question and get free reputation points? – Nicolas Gervais Jan 19 '20 at 22:16
  • First, my comments do constitute an answer (more than is perhaps desired). Second, it’s silly to answer the same, basic questions repeatedly, and (notionally) it’s less effort to find a duplicate. [Here’s one](https://stackoverflow.com/q/5767228/8586227) that you might like better, although I can’t change my close vote immediately to recommend it. – Davis Herring Jan 20 '20 at 00:44

1 Answers1

3

A bit late but I had a similar case recently.
You can use:

def activate(name1, name2):
    with Listener(on_press=lambda event: on_press(event, left=name1, right=name2)) as listener:
        listener.join()
KonKli
  • 31
  • 3