Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Speeding up an .exe created with Pyinstaller

I've converted my program (written in Python 3.6.1, converted using Python 3.5.3) from a .py to an .exe using Pyinstaller. However, it is incredibly slow at loading (it takes roughly 16 seconds, compared to the <1 second when running in IDLE), even after I optimised what I though the problem was (importing tons of modules, so I changed the code to only import the parts of the modules that are necessary). That sped it up a lot when running it in IDLE, but when I created an .exe out of it it was exactly the same (and I did check that I was using the right .py file). I seems like Pyinstaller just packages all modules that you have installed on your system into the .exe, instead of only the small parts of the modules that are actually being used (when using --onefile). How can I make sure that Pyinstaller only installs the necessary parts of the modules or otherwise speed it up, while still using --onefile and packaging it into a single .exe?

Full code:

from os import path, remove
from time import sleep
from sys import exit
from getpass import getuser
from mmap import mmap, ACCESS_READ


my_file = "Text To Speech.mp3"
username = getuser()
no_choices = ["no", "nah", "nay", "course not", "don't", "dont", "not"]
yes_choices = ["yes", "yeah", "course", "ye", "yea", "yh", "do"]


def check_and_remove_file():

    active = mixer.get_init()
    if active != None:
        mixer.music.stop()
        mixer.quit()
        quit()
    if path.isfile(my_file):
        remove(my_file)


def get_pause_duration(audio_length, maximum_duration=15):

    default_pause, correction = divmod(audio_length, 12)
    return min(default_pause + bool(correction), maximum_duration)


def exiting():

    check_and_remove_file()
    print("\nGoodbye!")
    exit()


def input_for_tts(message):

    try:

        tts = gTTS(text = input(message))
        tts.save('Text To Speech.mp3')
        with open(my_file) as f:
            m = mmap(f.fileno(), 0, access=ACCESS_READ)
        audio = MP3(my_file)
        audio_length = audio.info.length
        try:
            mixer.init()
        except error:
            print("\nSorry, no audio device was detected. The code cannot complete.")
            m.close()
            exiting()   
        mixer.music.load(m)
        mixer.music.play()
        sleep(audio_length + get_pause_duration(audio_length))
        m.close()
        check_and_remove_file()

    except KeyboardInterrupt:

        exiting()


from pygame import mixer, quit, error
from gtts import gTTS
from mutagen.mp3 import MP3


check_and_remove_file()


input_for_tts("Hello there " + username + ". This program is\nused to output the user's input as speech.\nPlease input something for the program to say: ")


while True:

    try:

        answer = input("\nDo you want to repeat? ").strip().lower()
        if answer in ["n", no_choices] or any(x in answer for x in no_choices):
            exiting()
        elif answer in ["y", yes_choices] or any(x in answer for x in yes_choices):
            input_for_tts("\nPlease input something for the program to say: ")
        else:
            print("\nSorry, I didn't understand that. Please try again with yes or no.")

    except KeyboardInterrupt:

        exiting()
like image 761
Gameskiller01 Avatar asked May 29 '17 21:05

Gameskiller01


People also ask

Does PyInstaller speed up code?

PyInstaller is a packaging system, not a compiler or an optimizer. Code packaged with PyInstaller does not run any faster than it would when run on the original system. If you want to speed up Python code, use a C-accelerated library suited to the task, or a project like Cython.

Why is PyInstaller so slow?

PyInstaller's bootloader is usually quite fast in one-dir mode, but it can be much slower in one-file mode, because it depacks everything into a temporary directory. On Windows, I/O is very slow, and then you have antiviruses that will want to double check all those DLL files. PyQt itself is a non-issue.

How do I reduce the size of the PyInstaller exe?

In order to reduce the size of exe file, we will use the packages that are bound to or installed by PIP instead of Conda. So, the trick is uninstall Conda packages and reinstall them again using pip in a new environment where is clean and fresh.

Which is better PyInstaller or py2exe?

In PyInstaller it is easy to create one exe, By default both create a bunch of exes & dlls. In py2exe its easier to embed manifest file in exe, useful for run as administrator mode in windows vista and beyond. Pyinstaller is modular and has a feature of hooks to include files in the build that you like.


1 Answers

have a look at the documentation, i guess that explains, why it is slow: https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#how-the-one-file-program-works

Short answer, a complete environment for your program needs to be extracted and written to a temporary folder.

Furthermore the one-file option is in contrast to what you expected: https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#bundling-to-one-file

like image 149
olisch Avatar answered Sep 29 '22 20:09

olisch