I'm trying make a python program initiating a nanosecond count when a key on the keyboard is pressed, stopping it when the key is released and calculating how long the key was pressed down for.
So far I have tried several different structures using the modules pynput and time. I release the code below is wrong, but I'm adding it anyway, so somebody could potentially pinpoint me in the right direction.
When I run the code below it does print a time in nanoseconds. However, the time printed keeps increasing for every key I try, no matter for how long I press the key down. It seems the method: time.perf_counter_ns() does not stop counting even when the function block is finished and called again after that.
import pynput, time
from pynput.keyboard import Key,Listener
timer = 0
timer2 = 0
def press(Key):
timer = time.perf_counter_ns()
def release(Key):
timer2 = time.perf_counter_ns()
print(timer-timer2)
with Listener(on_press=press, on_release=release) as listener:
listener.join()
It looks like your problem is that the line timer = time.perf_counter_ns()
in press
is not doing what you expect.
Variables assigned to within Python functions hide variables with the same name from the parent scope(s). This means that you're assigning to a local variable called timer
, rather than the global variable timer
as you expect. When you calculate timer-timer2
in release
, you're using the global variable timer
, the value of which never changes from 0
.
Wrap the timers in a class that contains timer
as a member.
class Timer:
def __init__(self):
self.timer = None
def press(self, key):
self.timer = time.perf_counter_ns()
def release(self, key):
timer2 = time.perf_counter_ns()
print(timer2 - self.timer)
timer = Timer()
with Listener(on_press=timer.press, on_release=timer.release) as listener:
listener.join()
Another way is to just use the global version of timer
in your code. This is considered bad practice, but here is how you'd do it.
def press(Key):
global timer
timer = time.perf_counter_ns()