Python Flask应用如何在后台运行函数以实现midi键盘输入监听?
解决方案
以下是可直接运行的修改后代码,已经解决后台线程启动、线程安全、数据重置等核心问题:
from flask import Flask, json import mido import threading app = Flask(__name__) # 存储按下的按键 notes_pressed = [] # 线程锁,保证共享变量读写安全,避免数据异常 note_lock = threading.Lock() # 请根据你的midi键盘实际最低音调整数值,88键标准钢琴最低音对应midi值为21(A0) lowest_key = 21 @app.route('/get_notes', methods=['GET']) def return_pressed_notes(): global notes_pressed with note_lock: # 先复制当前列表作为返回结果,再清空列表,保证每次返回的是两次请求间隔内的按键数据 res = notes_pressed.copy() notes_pressed.clear() return json.dumps(res) # 转换midi键号到音名 def translate_key(key_num): # 可根据自己的需求调整转换逻辑 note_names = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] octave = key_num // 12 note = note_names[key_num % 12] return f"{note}{octave}" # 后台监听midi输入的函数 def get_notes(): global notes_pressed with mido.open_input() as inport: for msg in inport: # 过滤有效按键事件 if msg.type=='note_on' and msg.velocity!=0 and msg.channel==0: with note_lock: notes_pressed.append(translate_key(msg.note - lowest_key)) if __name__ == '__main__': # 先启动后台midi监听线程,daemon设为True保证主进程退出时后台线程同步关闭 midi_thread = threading.Thread(target=get_notes, daemon=True) midi_thread.start() # 关闭debug模式,避免Flask重载导致后台线程重复启动、端口占用等问题 app.run(debug=False)
额外注意事项
- 如果你的设备存在多个midi输入端口,可先通过
mido.get_input_names()打印所有可用端口名,再在mido.open_input()中传入指定端口名即可 - 不需要每次请求清空历史按键的话,删掉
return_pressed_notes函数里的notes_pressed.clear()行即可 - 生产环境部署建议用Gunicorn等WSGI服务器,单worker启动即可避免多进程下出现多个重复midi监听线程的问题
内容的提问来源于stack exchange,提问作者Moses
相关产品推荐
相关产品推荐

