Python 应用程序在使用 stringIO 和 pygame.mixer.music.load() 时不会退出



我正在使用StringIO来流式传输音乐数据,但是当我使用pygame.mixer.music.load()运行时,我的应用程序似乎不会退出。即使我使用 close():

def PlaySong(self, song_id):
song = StringIO.StringIO(resp.read())
self.pygame.mixer.music.load(song)
....

该函数将返回,但必须杀死应用程序。如果我将响应保存到文件,然后加载文件名,它将关闭。有人可以帮忙吗?我不想使用本地存储。

更多信息。我在从文件打开和使用 stringio 时都做了一个跟踪,strace 将正确退出两个实例。痕迹看起来很干净。

工作代码:

def playsong():
mp3 = "/home/adam/Documents/pinyin/pinyinchart_win/pinyin/zuo2.mp3"
#with open(mp3, "rb") as outfile:
#    song = outfile.read()
#io = StringIO.StringIO(song)
pygame.init()
pygame.mixer.music.load(mp3)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(50)
#io.close()
#outfile.close()

不工作代码:

def playsong():
mp3 = "/home/adam/Documents/pinyin/pinyinchart_win/pinyin/zuo2.mp3"
with open(mp3, "rb") as outfile:
song = outfile.read()
io = StringIO.StringIO(song)
pygame.init()
#pygame.mixer.music.load(io)
pygame.mixer.music.load(mp3)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(50)
io.close()
outfile.close()

尝试 sys.exit() 和内置函数 exit()。

我有同样的问题 - 显然pygame在清理自己方面非常糟糕,调用pygame.quit()有时只是挂起。即使sys.exit()实际上也没有退出,可能是因为pygame.init()安装了一些错误处理程序。据#pygameIRC频道上的人说,这个问题永远不会得到解决,pygame是一个死项目(!?),尽管邮件列表和项目网站上似乎仍然有一些活动。也许这将在pygame2中修复...

当使用 Python 的线程支持时,我已经看到了这种行为。 pygame 可能正在使用线程,其中一些线程是隐式生成的,没有标记为"守护程序"线程,并且在您尝试.quit()时没有加入。

请注意,sys.exit()不太可能工作,因为这会引发 SystemExit 异常(可能会被捕获,特别是被atexit处理程序捕获)。 此外,sys.exit()只会退出处理它的线程,其他线程仍将运行。(StackOverflow:pygame中sys.exit()的问题以获取更多详细信息)。

这是另一个:StackOverflow:pygame屏幕在我关闭它时冻结。

我尝试了一些谷歌搜索这些短语:pygame退出{失败,挂起,停滞} ...他们中的大多数导致了类似于我在这里提供的这些讨论。

共识似乎是您希望构建线程来处理"quit"事件,以便在您的主(父)进程尝试使用sys.exit()或干脆退出__main__套件之前,所有线程都调用pygame.quit()。

除此之外,我还会检查某些进程、线程或驱动程序是否在您的音乐设备上停止。 在类Unix系统中,在进程列表(ps命令输出)中显示为处于"D"状态。 (我假设,通过你提到的strace,你是在Linux上运行的)。

我在尝试运行pykaraoke时经常遇到这个问题;直到今晚我才将其追溯到pygame.mixer.music.play()。 奇怪的是,它只发生在多处理器系统上;如果我在单处理器系统上进行测试,或者使用"maxcpus=1"启动 Linux,它不会发生。 否则,硬挂起会定期发生,我必须使用SIGKILL,因为SIGTERM不起作用。

所以我认为这是pygame中的一个错误,或者它所依赖的东西。 我刚刚将一个 Python 脚本和非常短的 (50k) MP3 文件发送到 pygame 用户邮件列表;如果发生什么事,我会报告。

更新:我能够使用直接与SDL_mixer交互的程序重现该错误。 答案是,这是 smpeg 中的一个错误。 重建SDL_mixer,并打开对 libmad 的支持。 您还必须完全卸载 smpeg,因为SDL_mixer会尝试使用它来支持 libmad。

最新更新