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()
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With