Python 2.7 当指定给自己的进程时,发声功能静音
我正在开发一款kivy应用程序,该应用程序旨在现场参数化制作耳朵训练练习,并进行播放。音乐使用mingus模块进行描述,并通过其FluidSync实现进行播放。我有一个练习播放功能,它在正常调用时按预期工作,但由于使用该方法,当演练运行时(在无限while循环上等待手动停止),其他所有内容都会挂起,因此不会产生可接受的行为。我使用Python 2.7 当指定给自己的进程时,发声功能静音,python-2.7,kivy,fluidsynth,Python 2.7,Kivy,Fluidsynth,我正在开发一款kivy应用程序,该应用程序旨在现场参数化制作耳朵训练练习,并进行播放。音乐使用mingus模块进行描述,并通过其FluidSync实现进行播放。我有一个练习播放功能,它在正常调用时按预期工作,但由于使用该方法,当演练运行时(在无限while循环上等待手动停止),其他所有内容都会挂起,因此不会产生可接受的行为。我使用process()将函数分配给它自己的进程,并根据终端的输出,它按预期循环,但没有声音。另一点值得注意的是,根据终端活动的节奏判断,多次按下“开始”按钮会导致多个进程并
process()
将函数分配给它自己的进程,并根据终端的输出,它按预期循环,但没有声音。另一点值得注意的是,根据终端活动的节奏判断,多次按下“开始”按钮会导致多个进程并行运行。以下是界面python端的代码:
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.config import Config
from classes import *
from multiprocessing import Process
import yaml
Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '700')
class Welcome(Screen):
pass
class Builtin(Screen):
pass
class DrillScreen(Screen):
def __init__(self, **kwargs):
super(DrillScreen, self).__init__(**kwargs)
self.options = kwargs['options']
self.desc = self.options.des
self.thedrill = drill(self.options)
desc = Label(
text=self.options.des,
size_hint_x=0.9,
size_hint_y=1)
button = Button(
text = 'Start',
size_hint=[0.4,0.1])
button.bind(on_release=self.startdrill())
self.add_widget(desc)
self.add_widget(button)
def startdrill(self):
def starter(*args):
proc = Process(target=self.thedrill.run)
proc.start()
return starter
class BuiltinView(RecycleView):
def __init__(self, **kwargs):
super(BuiltinView, self).__init__(**kwargs)
with open('builtin.yaml', 'r') as builtin:
self.drills = yaml.load(builtin)
self.data = [ {'text': self.drills[i]['name'],
'on_release': self.startermaker(i,self.drills[i])}
for i in sorted(self.drills.keys()) ]
def startermaker(self,num,options):
def startdrill():
options = drilloptions(self.drills[num])
drillscreen = DrillScreen(name='drill', options=options)
app = App.get_running_app()
app.root.add_widget(drillscreen)
app.root.current = 'drill'
#drillscreen.thedrill.run()
return startdrill
class Manager(ScreenManager):
pass
class TestingApp(App):
def build(self):
return Manager()
TestingApp().run()
drill
类在其属性中保存一些参数,并在调用其.run()
方法时进入循环,在这些参数中无休止地生成练习。在DrillScreen
类的button.bind()
语句中,如果我直接打开_release=self.drill.run,我会让函数正常工作。我不知道我错过了什么。如果需要,我可以发布项目其他组件的代码。谢谢。好吧,在尝试生成一个小的失败示例时,我偶然发现了一个修复方法。我真的不知道为什么它是一种方式而不是另一种方式。以前FluidSync是在drill
类的初始化方法中初始化的,创建时,我将其移动到运行方法中。非常粗略地说,几乎是伪代码:
之前:
class drill:
def __init__(self, opt):
#Some attribute setting
self.ex = None #This will instantiate a class describing a single question
fluidsynth.init(args)
def run(self):
while True:
#Determining randomly the arguments to create Exercise instance
self.ex = Exercise(args)
self.ex.play()
之后:
class drill:
def __init__(self, opt):
#Some attribute setting
self.ex = None
def run(self):
fluidsynth.init(args)
while True:
#Determining randomly the arguments to create Exercise instance
self.ex = Exercise(args)
self.ex.play()
当我用按钮直接调用.run()
时,这两个版本都可以工作。当我将其分配给自己的进程并将该进程交给button.bind()
时,只有第二个版本产生声音。因此,似乎发生的大致情况是,无法从不同的进程访问初始化的FluidSync
如果有人对此问题给出非推测性的理解,我将推迟接受此答案。我非常愿意帮助您,但您能否尝试将您的问题隔离到少于(比如)100行可运行代码?我的意思是,我将能够复制粘贴到我的IDE中,并立即运行它和玩它。谢谢。我试图编写的示例结果是按我所希望的那样工作。为了简洁起见,我在固定的音乐实体上调用了fluidsynth play函数。我想我对绑定函数作为参数传递的内容缺乏理解。例如,我将*args
放在starter()
的定义中,作为一个糟糕的解决方法,它以一种我无法理解的方式传递了一个按钮
实例。drill
类的.run()
方法依赖于许多属性,如果self
以某种方式被混淆,它可能会崩溃。我仍然会尝试写一个小但不成功的例子。是的,你走在正确的道路上——也许这会帮助你找到问题所在。然后,你可以编辑你的答案,并说问题100%确定地出现在第X行。你试过把这一行放在循环之前吗?多重初始化可能在这里起作用,也可能是时间的问题。@Tshirtman是的,这就是我到底在做的。我在这里输入它的草图时把它放错了位置(实际代码中有很多不相关的东西)。谢谢。