How To Pack Python Program Into exe File
After you have built your python program, you may want to distribute this program to your users to run by themselves. However, in most of the cases, your uses either may not have the access to install Python for executing the script nor have the knowledge to run script from command line. In this case, you will need to find a way to pack your program into some executable file, so that it can be run with a simply click like other apps. In this article, I will be sharing with you how to pack python program into exe file with PyInstaller library for Windows users.
Prerequisite
You will need to create a virtual environment for your python program and activate it with the below command. I will explain why this is needed later.
python -m venv test test\Scripts\activate.bat
Then install PyInstaller library:
pip install pyinstaller
Let’s get started
Let me first explain why we need to set up a virtual environment for your program. If you are concurrently working on different projects, and each of them are using a different set of python libraries, sometimes these libraries may conflict with each other due the version difference or other dependencies. In this case, you will need to use venv module to create a isolated python environment for each of your projects, so that each virtual environment only has the necessary libraries for running that particular python project.
Same comes when packing your program with PyInstaller, the virtual environment will ensure only the necessary libraries will be packed generating the executable file.
Build your Python program
For this article, our main objective is to demonstrate how to pack python program into exe file, so let’s just include some random library and write some dummy code.
And create a hello.py with the below code:
import requests
import sys, time
result = requests.get("https://www.google.com")
print(f"Google responded {result.status_code}")
with open("test.config") as f:
print(f.read()) for i in range(15, 0, -1):
sys.stdout.write("\r")
sys.stdout.write(f"Window will be closed in {i:2d} seconds")
sys.stdout.flush()
time.sleep(1)
Let’s also create a file at the current directory called “test.config” and write some random words, saying “some configurations”.
If you run it with python hello.py, you shall get something similar output to the below:
Google responded 200
some configuration
Window will be closed in 1 seconds
Everything is ready, let’s move to the next step to pack python program into exe file.
Pack python program into exe file with PyInstaller
The PyInstaller program is actually quite easy to use, everything comes with a default option. E.g., If you do not specify any parameter and just run the below:
You will be able to get a folder (onedir mode) under dist\hello, where you can find a hello.exe. But if you click to run it, it probably will auto close after a few seconds before you can see any error message.
The problem here is that, inside our program, we have some code to read some external file “test.config”, and this file was not packed into the dist\hello folder. Of course you can manually copy this file to dist\hello every time after you built the Python program, but there is a option you can use to tell PyInstaller to include the additional files.
--add-data option
This -add-data option can be used to include the additional file or directory. e.g.:
--add-data “src file or folder;dest file or folder”
If you have multiple files to be added, you can use this option multiple times. (for binary file, you may consider to use -add-binary option)
So you can re-run the below command to include the additional file, and also use -clean to clean up the directory before generating the files again.
pyinstaller hello.py --add-data "test.config;." --clean
--noconfirm option
You may see the warning similar to below to ask your confirmation to delete the old files, you can just key in “y” to confirm. This question can be avoided if you put the option --noconfirm.
WARNING: The output directory “c:\test\dist\hello” and ALL ITS CONTENTS will be REMOVED! Continue? (y/n)
So once the new exe file generated, you shall be able to run and see the below result:
So far so good, but still can be better. Let’s specify the name of the exe file, and make it one file rather than a directory.
--onefile vs --onedir
With the below extra options : --onefile and -name “SuperHero”, we shall expect to pack the Python program into a single SuperHero.exe file.
pyinstaller --onefile hello.py --name "SuperHero" --add-data "test.config;." --clean
When we try to execute this exe file, you would see some error like below. This is because when running the exe, PyInstaller unpack your data into a temp folder, and the temp folder path is set to sys._MEIPASS, which will be different from your original file path.
In this case, let’s modify our code again to cater for this:
import osdef get_resource_path(relative_path):
try:
# PyInstaller creates a temp folder and set the path in _MEIPASS
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path) with open(get_resource_path("test.config")) as f:
print(f.read())
When you rebuild the SuperHero.exe, this time you shall be able to execute it without any issue. And it also works perfectly if you rebuild your exe with -onedir mode.
--log-level
If you do not wish to see so many output messages when packing the program, you can turn it off by using the --log-level, the log level option can be one of TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL. For instance, --log-level=”ERROR” will only show any output with error, and you do not even see a “Building completed successfully” message after build completion as it is logged as INFO.
--noconsole
If you are working with some automation program like auto sending emails or auto save some attachments, which does not necessarily interact with users, you can use --noconsole option, so when you click to run your exe file, it does not show up any console window.
PyInstaller specification file
You may noticed after you run the pyinstaller command, there is a .spec file generated. This file keeps all the options you have used for your last build. So if you just want to rebuild your executable files without changing any option, you may use the below command:
pyinstaller - D SuperHero.spec
Conclusion
With the options covered in above, it should meet your basic needs to pack python program into exe file. You may also refer to the official document for the other options PyInstaller offers.
Originally published at https://www.codeforests.com on July 17, 2020.