Как правильно открыть и закрыть музыкальный файл для Pygame Mixer без зависания / зависания Python?
Я разрабатываю музыкальный проигрыватель в Python 2.7, и у меня есть проблема, которую я не могу решить.
Иногда необходимо отключить SD-карту, с которой я играю. Поскольку pygame по-прежнему сохраняет последний воспроизводимый файл открытым после команд pygame.mixer.stop() и pygame.mixer.quit(), размонтировать карту было невозможно.
Поэтому я изменил свой код, чтобы использовать команды открытия и закрытия файла, чтобы можно было правильно закрыть воспроизводимый файл перед размонтированием. Таким образом, размонтирование работает нормально.
Моя проблема в том, что Python всегда зависает во время воспроизведения первой музыки. Нет никаких исключений или сообщений об ошибках, воспроизведение просто останавливается, и программа не отвечает ни на какой пользовательский ввод, даже Ctrl+C не работает, чтобы завершить выполнение из оболочки.
Это зависание всегда происходит в случайное время, где-то между 1 и 40 секундами после начала игры. Если я открою файл напрямую с помощью команды pygame.mixer.music.load(myfile), не используя решение открытия / закрытия, у меня никогда не будет зависаний, программа воспроизводится правильно даже в течение нескольких часов.
Какое решение я должен использовать, чтобы правильно закрыть воспроизводимый файл (чтобы отключить карту памяти), а также избежать зависания программы?
Вот соответствующая часть моего кода. Он закрывает предыдущий сеанс воспроизведения и начинает воспроизведение нового файла.
FailedMusicLoad = 0
pygame.mixer.music.stop()
pygame.mixer.stop()
pygame.mixer.quit()
try:
PlayedMp3File.close()
except AttributeError:
pass
try: # test if selected music file can be loaded
PlayedMp3File = open(Selectedmp3)
except IOError:
FailedMusicLoad = 1
if FailedMusicLoad <> 1:
pygame.mixer.init(frequency=musicforlength.info.sample_rate)
pygame.mixer.music.set_volume(MainVolume)
pygame.mixer.music.load(PlayedMp3File)
pygame.mixer.music.play()
2 ответа
Вы можете сначала попытаться загрузить весь файл в память, используя отображенный в памяти файл:
import mmap
...
with open(Selectedmp3) as f:
PlayedMp3File = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
pygame.mixer.music.load(PlayedMp3File)
pygame.mixer.music.play()
Таким образом, вы только касаетесь файла, загружая его в память и используя with
гарантирует, что он будет правильно закрыт.
Я нашел простой способ обойти SD-карту.
Перед размонтированием я открываю фиктивный mp3-файл не с SD-карты, а из локальной файловой системы с помощью команды pygame.mixer.music.load(). Я не начинаю проигрывать этот фиктивный файл, просто откройте его. После этого нет никаких проблем, SD-карта, кажется, правильно выпущена Pygame, и я могу размонтировать ее.