将全局退出信号转换为异常



我正在开发基于VLC和Curses的终端接口音频播放器。

最近在SE代码审查帖子中建议我利用异常退出程序,而不是使用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

使用系统退出:

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 上。谢谢你的时间。

这不是我发布的原始问题的答案,因为它不使用例外,所以我不会将其标记为解决方案。无论如何,正如注释中指出的那样,在 Pynput 回调上返回 false 会结束侦听器线程。监视该侦听器线程的状态可以告诉您何时关闭第二个"UI"线程:

def on_press(key: Key, view: View, player: Player):
"""Handle input"""
# boring code
elif key == 'q':
view.notify('Exiting...')
return False # kills listener thread
return True
def main():
view = View()
player = Player()
listener = Listener(on_press=partial(on_press, view=view, player=player))
listener.start()
while listener.running: # once the listener thread exits, end the program
tick(view, player)
del player
del view

最新更新