PyInstaller打包Python RPG程序出现多实例问题的解决求助
PyInstaller打包Python RPG游戏后出现多实例运行问题
我用Python开发了一款RPG游戏,为了给没有Python环境的朋友展示进度,用PyInstaller把脚本打包成了.exe文件。但测试时发现程序会多实例运行,我怀疑这和使用multiprocessing模块有关,但不知道怎么用freeze_support()解决这个问题。最终我改用threading和pygame替代multiprocessing与playsound,解决了问题。
原始代码
import random import os import sys import time from playsound import playsound import multiprocessing class Unit: def __init__(self, name, hp, strength, defense): self.name = name self.hp = hp self.strength = strength self.defense = defense def __str__(self): return f"""Name: {self.name} HP : {self.hp} STR : {self.strength} DEF : {self.defense} \n""" def attack(self, enemy): input("Press Enter to continue \n") print(f"{self.name} attacks {enemy.name}!") randomVariable = random.randint(0, 100) if randomVariable < 70: damage = self.strength - enemy.defense damage = notLessZero(damage) print(f"{self.name} hits {enemy.name} for {damage}!") enemy.hp -= damage enemy.hp = notLessZero(enemy.hp) print(enemy) else: print("Miss!") def notLessZero(variable): return max(0, variable) def battle(playerUnit, enemyUnit): while enemyUnit.hp > 0: playerUnit.attack(enemyUnit) def loopingMusic(soundFile): while True: playsound("music/cats.wav") def main(): name = input("What's your name? \n") print("a") p = multiprocessing.Process(target=loopingMusic, args=("cats.wav",)) p.start() print("b") playerUnit = Unit(name, 5, 6, 2) enemyUnit = Unit("Enemy", 5, 2, 3) print("c") print(playerUnit) print(enemyUnit) print("d") battle(playerUnit, enemyUnit) print("e") p.terminate() print("f") playsound('music/riff.wav', block = False) print("g") print("Enemy defeated\n") input("Congatulations\n") if __name__ == '__main__': sys.exit(main())
问题原因
在Windows系统下,PyInstaller打包带有multiprocessing的脚本时,会因进程启动机制触发多实例问题。Windows没有fork系统调用,multiprocessing需通过重新导入主模块创建子进程,打包后的exe在导入时会重复执行主程序逻辑,导致多实例运行。
用freeze_support()的解决方式
如果要继续使用multiprocessing,需在主入口最开始位置添加multiprocessing.freeze_support(),修改后的主入口代码如下:
if __name__ == '__main__': multiprocessing.freeze_support() sys.exit(main())
该函数会告知multiprocessing当前处于打包后的环境,避免重复启动主程序实例。
最终采用的替代方案
由于对freeze_support()的应用不熟悉,我改用threading线程来处理循环音乐播放,同时用pygame替代playsound处理音频,既规避了多进程带来的打包问题,也实现了音乐循环播放的需求。
内容的提问来源于stack exchange,提问作者Nabil Darwish
相关产品推荐
相关产品推荐

