19

I've managed to get pyinstaller to run more or less correctly now, except that it opens too many windows. It's pygame project, and it keeps loading the entire thing over again every second or so. My PC fills with game windows after a few seconds and everything grinds to a halt.

Running it from commandline, I can just see print outs saying the app is starting pasted over and over again in commandline window. As far as I can tell the Apps aren't closing or exiting, just spawning more and more.

The command I call to start pyinstaller is this:

pyinstaller --onedir main_local.py

The main file looks like this:

# Library imports
import pygame

# Project imports
from multiroidal_client    import MultiroidalClient
from settings              import *
import time

# Main program function
def main():

    # Initialise game class
    game = MultiroidalClient(SCREEN_SIZE, ('127.0.0.1', 8080))

    # Start game loop
    game.main_game_loop()


# Execute main function
if __name__ == '__main__':
    main()

I tried commenting out the if __ name __ ... bit to see if for some reason it was executing the main function and calling a duplicate each time by accident or something. When commented out the exec does nothing, as you might expect.

Any ideas? I've not included any more code because there is loads of it, and I'm not sure which parts are relevant. Let me know if you need to see anything else.

Cheers

EDIT: I added a quick print after the game.main_game_loop() just to check if the script jumped out of the infinite game loop. No such luck. It's loading a parallel instances of the scripts, all running simultaneously.

EDIT: I looked through the pyinstaller docs and managed to get some more debug out. Not sure if it's relevant or not, but here it is. This screen of dialog just keeps reprinting over and over again. I also tried the --noupx option which can sometimes help apparently - no such luck.

enter image description here

Oliver
  • 1,395
  • 1
  • 14
  • 33

2 Answers2

44

Multiprocessing!

I tried some simpler python programs, and they packaged up all fine. So it wasn't a problem with my method it was the code. Thinking about it again, it must be some unusual or difficult to package code in the project. Hmmm, maybe threading?

I've got a couple of threads running in parallel, and they are multiprocessing threads. After googling about I found this magic fix.

You simply stick this line, multiprocessing.freeze_support(), straight after if __name__ == "__main__" and before you call the main() function.

if __name__ == '__main__':

    # Pyinstaller fix
    multiprocessing.freeze_support()

    main()

It looks like the guys who develop the multiprocessing module had to include a hack to allow freeze packaging (py2exe, pyinstaller etc). Seems weird it isn't included a bit more smoothly. If you leave that freeze_support() call in, it still works even when you aren't running from packaged code as opposed to standard python files.

Anyway, if you are freezing/pacakaging code up and it seems to execute itself over and over, check if you are use multiprocessing. A simple google "multiprocessing pyinstaller" gave the answer.

FYI this only works on --onedir mode, --onefile mode is a different story and not supported on windows. You'll have to dig around more to solve that one.

Oliver
  • 1,395
  • 1
  • 14
  • 33
  • 5
    You are a live saver! This deserves a higher rating! Never thought I would find a solution to that this quick - THX – hypnomaki Feb 08 '17 at 12:06
  • I observed that PyInstaller monitoring processes call the main script repeatedly after a few seconds, but only the main process gets past `freeze_support()`. To keep the monitoring processes as lean as possible, I recommend importing all "heavy" modules such as matplotlib, seaborn, scipy, or your own evil creations AFTER `freeze_support()`. In my case, this reduced the CPU load (for the monitoring processes) considerably. Note: This applied to MacOS, python 3.6, PyInstaller 3.5) – normanius Oct 17 '19 at 17:57
  • I had a module I made that I imported into my main file that I wanted to turn into an exe. Even after putting this in the imported module (which fixed one error), the main module would repeatedly print a statement, so I had to put this in the main script as well, which fixed that problem :). – Shmack Sep 25 '22 at 06:15
  • I'm not even using multiprocessing and it solved my issue. In my case this could be related to sqlite3 (maybe it uses multiprocessing internally?). – Louis Lac Jan 07 '23 at 18:17
1

I am using Pytorch to generate executable file. Works fine when run .py file, however when I generated exe file using pyinstaller, it's keep loop.

python -F inference_resnet101.py

This saves me:

if __name__ == '__main__':

# Pyinstaller fix
multiprocessing.freeze_support()

main()
ssuperczynski
  • 3,190
  • 3
  • 44
  • 61
user158615
  • 31
  • 3