pythonpyinstallerpython-multiprocessing

pyinstaller executable creates multiple instances of the programme. How to stop it from doing so? (Python)


I am trying to make an RPG in Python and I wanted to show the progress of it to a friend. Problem is that my friend doesn't have Python on his system and I figured I should make an executable. I used pyinstaller to help change my script into an .exe file. Problem was, when I tested the exe file, it created multiple instances of the programme. I do not understand why this occurs.

Here is my code.

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())

Message log when I used pyInstaller (1/2)

Message log when I called pyInstaller (2/2)

Testing out the executable. Giving weird results

I suspect it has something to do with me using multiprocessing but I cannot find much about this though I would be happy to be corrected here. Ideally, from my code, it should simply progress from a to g without the letters repeating.

Edit: I was suggested this question: multiprocessing problem [pyqt, py2exe]

However, I am not using freezeSupport() for my application and I do not quite know how to apply it to my problem here.

Edit 2: I solved the problem. Instead of using multiprocessing, I used thread instead and instead of playsound, I use pygame instead


Solution

  • Add multiprocessing.freeze_support() at the beginning of your main().

    def main():
        multiprocessing.freeze_support()  # add this line
        name = input("What's your name? \n")
        print("a")
        p = multiprocessing.Process(target=loopingMusic, args=("cats.wav",))
        p.start()
        ...
    

    Build the exe again and the porblem should be solved.