Я работаю над аудиоплеером с терминальным интерфейсом на основе VL C и Curses.
Недавно мне посоветовали написать на SE Code Review пост , чтобы использовать исключения для выхода из программа вместо использования логического global
в качестве сигнала.
Однако, когда я преобразовал код в исключение SystemExit
, он полностью прекратил выход и вместо этого зависает до закрытия окна терминала. Я полагаю, что проблема связана со слушателем Pynput и тем, как я обрабатываю поток, который он создает, но я не уверен.
Использование логического значения:
import sys, os
from pynput import keyboard
from functools import partial
import cfg
from view import View
from player import Player
exit_signal: bool = False
def on_press(key: keyboard.KeyCode, view: View, player: Player):
"""Handle input"""
global exit_signal
key = str(key).strip('\'')
if str(key) == 'p':
view.notify('Playing...')
player.play()
elif key == 'a':
view.notify('Paused')
player.pause()
elif key == 'n':
view.notify('Skipping Forward...')
player.skip_forward()
elif key == 'l':
view.notify('Skipping Back...')
player.skip_back()
elif key == 'q':
view.notify('Exiting...')
exit_signal = True
del player
del view
return
view.update_ui(player.get_metadata())
def tick(view: View, player:Player):
"""For functions run periodically"""
metadata = player.get_metadata()
view.update_ui(metadata)
view = View()
player = Player()
view.notify("Ready!")
with keyboard.Listener(on_press=partial(on_press, view=view, player=player)) as listener:
while exit_signal == False:
tick(view, player)
listener.join() # merge to one thread
os.system('reset') # clean up the console
Использование SystemExit:
from os import system
from pynput import keyboard
from functools import partial
import cfg
from view import View
from player import Player
def on_press(key: keyboard.KeyCode, view: View, player: Player):
"""Handle user input"""
key = str(key).strip('\'')
if str(key) == 'p':
view.notify('Playing...')
player.play()
elif key == 'a':
view.notify('Paused')
player.pause()
elif key == 'n':
view.notify('Skipping Forward...')
player.skip_forward()
elif key == 'l':
view.notify('Skipping Back...')
player.skip_back()
elif key == 'q':
view.notify('Exiting...')
del player
del view
raise SystemExit
view.update_ui(player.get_metadata())
def tick(view: View, player: Player):
"""For functions run periodically"""
metadata = player.get_metadata()
view.update_ui(metadata)
view = View()
player = Player()
view.notify("Ready!")
listener = keyboard.Listener(
on_press=partial(on_press, view=view, player=player))
listener.start()
try:
while True:
tick(view, player)
except SystemExit:
listener.join() # merge back to one thread
os.system('cls' if os.name == 'nt' else 'clear')
Я ожидал бы, что оба фрагмента будут вести себя одинаково и выйдут при нажатии клавиши 'q', но вместо этого правильно будет работать только логический метод.
Этот код также на github . Спасибо за ваше время.