Python线程仅在从另一个模块调用时工作
我正在开发一个应用程序,该应用程序在Kivy应用程序中使用Mido接受MIDI键盘输入。目标是让一个线程不断轮询MIDI输入并将事件路由到PyFluidSync,而传统的Kivy应用程序正在并行运行。我需要某种并行处理,否则KivyUI会在循环运行时冻结midi轮询 在做了很多修改之后,我让它开始工作了,但我有点担心代码。我尝试在[if name==main]下启动线程,但只能运行一个进程,然后运行另一个进程 然后,由于意外,我在mido_midi.py中留下了最后两行代码,从而获得了预期的效果,这两行代码最初只是用于测试。现在,当我运行main.py时,我会得到应用程序和键盘输入。当我关闭应用程序时,除了一些丑陋的行为外,事情似乎按照我想要的方式进行 我担心的是,通过调用main中的所有内容,我似乎无法使线程正常工作。因为一切都在运转,我不明白为什么,我觉得这是不对的。我想我会把它扔给更聪明的人来获得洞察力 我做得对吗?如果没有,我需要改变什么?谢谢 main.py:Python线程仅在从另一个模块调用时工作,python,kivy,python-multithreading,midi,Python,Kivy,Python Multithreading,Midi,我正在开发一个应用程序,该应用程序在Kivy应用程序中使用Mido接受MIDI键盘输入。目标是让一个线程不断轮询MIDI输入并将事件路由到PyFluidSync,而传统的Kivy应用程序正在并行运行。我需要某种并行处理,否则KivyUI会在循环运行时冻结midi轮询 在做了很多修改之后,我让它开始工作了,但我有点担心代码。我尝试在[if name==main]下启动线程,但只能运行一个进程,然后运行另一个进程 然后,由于意外,我在mido_midi.py中留下了最后两行代码,从而获得了预期的效果
from kivy.app import App
from kivy.uix.widget import Widget
from mido_midi import start_synth, KeyboardInput
class MyApp(App):
def build(self):
return GameWidget()
class GameWidget(Widget):
def __init__(self, **kwargs):
super().__init__(**kwargs)
...
self.midikeyboard = KeyboardInput()
...
if __name__ == "__main__":
app = MyApp()
app.run()
mido_midi.py:
import mido
import fluidsynth
import threading
def start_synth(driver, sound, channel=0):
fs = fluidsynth.Synth(samplerate=24000, gain=0.8)
fs.start(driver)
sfid = fs.sfload(sound)
fs.program_select(channel, sfid, 0, 0)
# print("Midi loaded...")
return fs
class KeyboardInput(threading.Thread):
def __init__(self, device='Keystation 88 Port 1', driver='coreaudio', sound='sounds/Wii_Grand_Piano.sf2', channel=0):
super(KeyboardInput, self).__init__()
self.played_notes = []
self.device = device
self.driver = driver
self.sound = sound
self.channel = channel
self.inport = mido.open_input(self.device)
self.fs = start_synth(self.driver, self.sound)
def run(self):
for msg in self.inport:
print(msg)
note = msg.note
velocity = msg.velocity
self.fs.noteon(self.channel, note, velocity)
# Code outside of the class, intended for testing
m = KeyboardInput()
m.start()
当您执行from mido_midi import start_synth时,您的代码正在启动KeyboardInput线程,此时将执行KeyboardInput和测试行。if _uname _==\u_umain _u;:是一个构造,旨在防止在导入包含该构造的文件时发生这种情况。另外,请注意,您有两个不同的键盘输入实例。不确定这是否是你的意图
只需在if _uname _u==\u_umain _u;:块中添加相同的两行,就可以启动该块中的线程:
m = KeyboardInput()
m.start()
如果你真的只需要一个键盘输入实例,你应该可以这样做
self.midikeyboard.start()
在GameWidget中的_init__方法中
此外,如果希望更轻松地关闭,请在构造函数调用中添加daemon=True,或者:
m = KeyboardInput(daemon=True)
或
daemon=True意味着一旦应用程序完成,线程就会被终止
self.midikeyboard = KeyboardInput(daemon=True)