Заморозить основной поток

Как грамотней заморозить основной поток?


К примеру есть безтерминальный (.pyw) (*1) скрипт

import threading
import keyboard

class Test(threading.Thread):

    def __init__(self):
        super().__init__()

    def run(self):

        while True:
            print("kill me")

def Trigger():
    Test().start()

keyboard.add_hotkey("alt+f1", Trigger)

(*1) То есть применение терминальных input(), msvcrt.getch() и прочего не подходит.

Смысл данного в том, чтобы запускать некоторое действие при нажатии некоторой комбинации клавиш. Для этого удобней всего использовать keyboard, однако, добавив горячую клавишу, основная программа, конечно же, завершается, что не соответствует задумке. Тут основная программа должна зависнуть в угоду дочерним потокам-ждунам нажатия комбинации (~созданы keyboard, не модифицируемы).


while True: pass

, поднимающий CPU до 50% неприемлем.


while True: time.sleep(2**15)

мне бы хотелось избежать (Считайте, что это в учебных целях).


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

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

Тут основная программа должна зависнуть в угоду дочерним потокам-ждунам нажатия комбинации

while True: time.sleep(2**15) 

мне бы хотелось избежать (Считайте, что это в учебных целях).

Ок. Вы хотите, чтобы поток программы "завис". Какие для этого у вас есть варианты?

  • Ждать ввода с терминала - вам это не подходит, едем дальше
  • Гонять пустой цикл - чревато сильной загрузкой процессора, вам не подходит
  • Сделать один очень длинный sleep, либо гонять в цикле маленькийsleep, чтобы отдавать процессорное время другим потокам, пока ваш поток чего-то как бы ждёт - опять же вам не подходит "в учебных целях"
  • Остаются объекты модуля threading: Event либо Condition. И вот они то вам, похоже, могут подойти.

Просто бесконечно ждём, пока будет выставлен флаг у события. Практически не занимая при этом время процессора. И это, кстати, одна из самых правильных парадигм ожидания - мы не тратим процессор и при этом ждём выставления флага, чтобы сделать какое-то действие сразу после того, как флаг будет выставлен. Внутренне это реализуется специальными механизмами ОС, без "костылей" из инструкций sleep.

from threading import Event
event = Event()
event.wait()
→ Ссылка