Как сделать чтобы во время цикла работал punput?

Я хочу создать программу, похожую на автокликер. И когда пользователь нажмет клавишу F1, она запустится, и наоборот.

Здесь я использовал pynput, при необходимости я могу изменить его, только как заставить его выйти из функции, когда пользователь нажимает F1?

Я хотел создать программу автокликера с биндами. Но я получил бесконечный цикл, когда нажал клавишу F1.
Как это исправить?

from pynput.keyboard import Key, Listener
from time import sleep

class Logger:
    def __init__(self) -> None:
        self.is_active = False
        
    def pressed(self, key):
        if key == Key.f1:
            self.is_active = not self.is_active
            print(self.is_active)
            if self.is_active:
                while True:
                    print("Hello World!")
                    sleep(5)

if __name__ == '__main__':
    logger = Logger()
    with Listener(on_press=logger.pressed) as listener:
        listener.join()
    

Ответы (2 шт):

Автор решения: mrBars1k

Проблема в том, что цикл в функции pressed блокирует выполнение программы и не получится остановить его после его запуска.

Вместо бесконечного цикла внутри функции, вы можете использовать флаг для управления и остановки цикла.

Также нужно, чтобы цикл выполнялся в отдельном потоке, и затем использовать флаг для завершения этого цикла.

Цикл будет запускаться при первом нажатии F1 и останавливаться, если нажать снова.

Поток используется для выполнения цикла, а при повторном нажатии F1 поток останавливается и создаётся новый при следующем нажатии.

from pynput.keyboard import Key, Listener
import time
import threading


class Logger:
    def __init__(self) -> None:
        self.is_active = False
        self.thread = None

    def pressed(self, key):
        if key == Key.f1:
            self.is_active = not self.is_active
            print(self.is_active)
            if self.is_active:
                if not self.thread or not self.thread.is_alive():
                    self.thread = threading.Thread(target=self.run_loop)
                    self.thread.start()
            else:
                self.thread = None

    def run_loop(self):
        while self.is_active:
            print("Hello World!")
            time.sleep(5)


if __name__ == '__main__':
    logger = Logger()
    with Listener(on_press=logger.pressed) as listener:
        listener.join()
→ Ссылка
Автор решения: S. Nick

Как вариант:

from pynput.keyboard import Key, Listener
from time import sleep


class Logger:
    def __init__(self) -> None:
        self.is_active = False
        self.stop = False
        
    def pressed(self, key):
        if key == Key.f1:
            self.is_active = not self.is_active
            
        elif key == Key.esc:
            self.stop = True
      

if __name__ == '__main__':
    logger = Logger()
#    with Listener(on_press=logger.pressed) as listener:
#        listener.join()

    listener = Listener(on_press=logger.pressed)
    listener.start()
    while not logger.stop:
        #print(f"F1: {logger.is_active}; logger.stop: {logger.stop}")
        sleep(0.5)
        if logger.is_active:
            print("Hello World!")
            
    print(f"\nKey.esc: listener.stop() \n{'=' * 33} \n")    
    listener.stop()

введите сюда описание изображения

→ Ссылка