Как сделать программу python, измеряющую наносекунды между динамикой нажатия клавиш?

Я пытаюсь создать программу на Python, инициирующую отсчет наносекунд при нажатии клавиши на клавиатуре, останавливая ее при отпускании клавиши и вычисляя, как долго клавиша была нажата.

До сих пор я пробовал несколько разных структур, используя модули pynput и time. Я выпускаю приведенный ниже код неправильно, но я все равно добавляю его, чтобы кто-то потенциально мог указать мне правильное направление.

Когда я запускаю приведенный ниже код, он печатает время в наносекундах. Однако напечатанное время продолжает увеличиваться для каждой клавиши, которую я нажимаю, независимо от того, как долго я нажимаю клавишу. Кажется, метод: time.perf_counter_ns() не перестает считать, даже когда функциональный блок завершается и вызывается снова после этого.

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()

person joecode    schedule 16.06.2020    source источник
comment
Простой шаг отладки, который мог бы помочь: print(timer) в release(), и вы увидите, что это всегда 0. Также ваша арифметика дает отрицательное число: вы должны поменять местами операнды.   -  person msanford    schedule 17.06.2020


Ответы (1)


Источник ошибки

Похоже, ваша проблема в том, что строка timer = time.perf_counter_ns() в press не делает того, что вы ожидаете.

Переменные, назначенные внутри функций Python, скрывают переменные с тем же именем из родительской области (областей). Это означает, что вы присваиваете значение локальной переменной с именем timer, а не глобальной переменной timer, как вы ожидаете. Когда вы вычисляете timer-timer2 в release, вы используете глобальную переменную timer, значение которой никогда не меняется с 0.

Решение

Оберните таймеры в класс, который содержит timer в качестве члена.

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()

Другой способ — просто использовать глобальную версию timer в своем коде. Это считается плохой практикой, но вот как это сделать.

def press(Key):
    global timer
    timer = time.perf_counter_ns()
person Emerson Harkin    schedule 16.06.2020
comment
@joecode Помимо пометки как принятого, вы также можете проголосовать за него. Голоса не ограничены и их можно бесплатно раздавать, используйте их свободно :) - person msanford; 17.06.2020
comment
Да, я действительно это сделал, но, поскольку я новичок в stackoverflow, появилось сообщение о том, что голоса, отданные теми, у кого репутация менее 15, не отображаются публично. Еще 2, и вы это увидите. - person joecode; 18.06.2020