Приложение 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)
    ....

Функция вернется, но приложение придется убить. Если я сохраню ответ в файл, а затем загружу имя файла, он закроется. Кто-нибудь может помочь? Я не хочу использовать локальное хранилище.

Больше информации. Я сделал strace как при открытии из файла, так и при использовании 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()

person AdamL    schedule 18.10.2012    source источник
comment
Вы вызываете close() для объекта resp? Как выйти из приложения?   -  person sloth    schedule 18.10.2012
comment
Да, resp.close() вызывается до song.close()   -  person AdamL    schedule 18.10.2012
comment
Попробуйте позвонить pygame.quit() до того, как ваше приложение закроется.   -  person Whatang    schedule 19.10.2012
comment
Есть ли шанс, что вы запустите его в IDLE?   -  person cerealy    schedule 19.10.2012
comment
Нет, я запускаю его в командной строке.   -  person AdamL    schedule 24.10.2012


Ответы (4)


Попробуйте sys.exit() и встроенную функцию exit().

person alexpinho98    schedule 02.04.2013

У меня та же проблема - видимо, pygame довольно плохо убирает за собой, а вызов pygame.quit() иногда просто зависает. Даже sys.exit() на самом деле не завершается, возможно, из-за некоторых обработчиков ошибок, установленных pygame.init(). По словам людей на IRC-канале #pygame, эта проблема никогда не будет решена, а pygame — мертвый проект (!?), несмотря на то, что в списке рассылки и на веб-сайте проекта все еще есть активность. Возможно, это будет исправлено в pygame2...

person anarcat    schedule 07.04.2013

Я видел такое поведение, когда используется поддержка потоков Python. Возможно, что pygame использует потоки и что некоторые из них создаются неявно, не помечаются как потоки «демона» и не присоединяются в то время, когда вы пытаетесь выполнить .quit().

Обратите внимание, что sys.exit() вряд ли сработает, потому что вызывает исключение SystemExit (которое может быть перехвачено, в частности, обработчиками atexit). Кроме того, sys.exit() закроет только тот поток, в котором он был обработан, другие потоки продолжат работу. (StackOverflow: Проблема с sys.exit() в pygame для получения дополнительной информации об этом).

Вот еще: StackOverflow: экран pygame зависает, когда я его закрываю.

Я попробовал несколько поисков в Google по фразам: pygame quit {сбой, зависание, зависание}... и большинство из них привели к обсуждениям, подобным тем, которые я предоставил здесь.

Похоже, консенсус заключается в том, что вы хотите структурировать свои потоки для обработки события «выход», чтобы все они вызывали pygame.quit() до того, как ваш основной (родительский) процесс попытается использовать sys.exit() или просто выпадает из набора __main__.

Кроме того, я бы также проверил, не зависает ли какой-либо процесс, поток или драйвер на вашем музыкальном устройстве. В Unix-подобных системах это будет отображаться в списке процессов (вывод команды ps) как находящееся в состоянии «D». (По вашему упоминанию strace я предполагаю, что вы работаете в Linux).

person Jim Dennis    schedule 07.04.2013

Я часто сталкивался с этой проблемой при попытке запустить pykaraoke; только сегодня вечером я проследил его до pygame.mixer.music.play(). Странно то, что это происходит только на многопроцессорных системах; если я выполняю тест на однопроцессорной системе или загружаю Linux с "maxcpus=1", этого не происходит. В противном случае жесткое зависание происходит регулярно, и мне приходится использовать SIGKILL, потому что SIGTERM не работает.

Так что я думаю, что это ошибка в pygame или что-то, от чего это зависит. Я только что отправил сценарий Python и очень короткий (50 КБ) файл MP3 в список рассылки пользователей pygame; если что случится, отчитаюсь.

ОБНОВЛЕНИЕ: мне удалось воспроизвести ошибку с помощью программы, которая напрямую взаимодействовала с SDL_mixer. Ответ: это ошибка в smpeg. Пересоберите SDL_mixer с включенной поддержкой libmad. Вы также должны полностью деинсталлировать smpeg, потому что SDL_mixer попытается использовать его в пользу libmad.

person ulatekh    schedule 06.04.2013