Как можно прервать выполнение цикла while true с помощью нажатия клавиши?

Как правильно реализовать выход из цикла по нажатию клавиши, учитывая, что использование `time.sleep` мешает корректной обработке событий? Я заметил, что для решения этой проблемы следует использовать многопоточность или асинхронный код. Привожу примеры своих попыток (несколько раз менял порядок строк, но, увы, без успеха — либо код выполняется один раз и кнопка работает, либо кнопка активна в моменты, когда не работает `time.sleep`). 

```python
def loop1():
    while True:
        pyautogui.moveTo(h,z-z,0.21)
        time.sleep(0.1)
        pyautogui.mouseDown(button='right')
        time.sleep(3)
        pyautogui.moveTo(t,r,0.1)
        time.sleep(0.11)
        pyautogui.mouseUp(button='right')
        pyautogui.press('Q')
        time.sleep(0.22)

def loop2():
    while True:
        if keyboard.is_pressed('J'):
            sys.exit()

Thread(target=loop1).start()
Thread(target=loop2).start()
```

```python
async def kek1():
    pyautogui.moveTo(h,z-z,0.21)
    await asyncio.sleep(0.1)

async def kek2():
    pyautogui.mouseDown(button='right')
    await asyncio.sleep(3)

async def kek3():
    pyautogui.moveTo(t,r,0.1)
    await asyncio.sleep(0.11)

async def kek4():
    pyautogui.mouseUp(button='right')
    pyautogui.press('Q')
    await asyncio.sleep(0.22)

async def kek5():
    while True:
        if keyboard.is_pressed('J'):
            sys.exit()

async def main():
    while True:
        await asyncio.gather(kek1(), kek2(), kek3(), kek4(), kek5())
```

```python
async def kek1():
    while True:
        pyautogui.moveTo(h,z-z,0.21)
        await asyncio.sleep(0.1)
```
  • 20 октября 2024 г. 18:42
Ответы на вопрос 2
Вы правы, использование `time.sleep()` в циклах, которые обрабатывают события нажатий клавиш, вызывает проблемы, так как блокирует основной поток выполнения и мешает реагировать на события. Вместо этого можно использовать асинхронное программирование или многопоточность.

Давайте рассмотрим оба подхода:

### 1. Использование многопоточности

Вы можете запустить два потока: один для выполнения основной логики, а другой для проверки нажатия клавиш. Код в вашем примере можно немного почистить и улучшить:

```python
import pyautogui
import keyboard
import time
import sys
from threading import Thread

def loop1():
    while True:
        pyautogui.moveTo(h, z-z, 0.21)
        time.sleep(0.1)
        pyautogui.mouseDown(button='right')
        time.sleep(3)
        pyautogui.moveTo(t, r, 0.1)
        time.sleep(0.11)
        pyautogui.mouseUp(button='right')
        pyautogui.press('Q')
        time.sleep(0.22)

def loop2():
    while True:
        if keyboard.is_pressed('J'):
            sys.exit()

# Запуск потоков
Thread(target=loop1, daemon=True).start()
Thread(target=loop2, daemon=True).start()

# Блокировка основного потока
while True:
    time.sleep(1)
```

### 2. Использование асинхронного подхода

Если вы хотите использовать асинхронные функции, вам необходимо сделать так, чтобы ваши задачи не блокировали выполнение. Обратите внимание, что при использовании `asyncio` вам нужно убедиться, что все функции, которые блокируют выполнение, также реализованы быстрее:

```python
import pyautogui
import keyboard
import asyncio
import sys

async def move_mouse():
    while True:
        pyautogui.moveTo(h, z-z, 0.21)
        await asyncio.sleep(0.1)
        pyautogui.mouseDown(button='right')
        await asyncio.sleep(3)
        pyautogui.moveTo(t, r, 0.1)
        await asyncio.sleep(0.11)
        pyautogui.mouseUp(button='right')
        pyautogui.press('Q')
        await asyncio.sleep(0.22)

async def check_key():
    while True:
        if keyboard.is_pressed('J'):
            sys.exit()
        await asyncio.sleep(0.1)  # Небольшая задержка для снижения нагрузки

async def main():
    await asyncio.gather(move_mouse(), check_key())

# Запуск асинхронного выполнения
asyncio.run(main())
```

### Пояснения:
1. В первом примере с многопоточностью используется `daemon=True`, чтобы потоки завершались вместе с основным процессом.
2. Во втором примере для асинхронного подхода важно добавить задержку в `check_key()`, чтобы избежать загрузки ЦП. 
3. Если используете `keyboard`, убедитесь, что библиотека поддерживает работу в вашей среде (иногда могут быть проблемы в средах, отличных от консоли, например, в IDE).

Если у вас сложные или длительные задачи, всегда лучше использовать асинхронные функции, чтобы избежать блокировок.
попробуй так 
async def kek2(event):
"""реагирует на нажатие клавиш"""
while true:
if keyboard.is_pressed('J'):
sys.exit()
if event.key == pygame.K_q:
sys.exit()
Похожие вопросы