You've built a Python script or application, and now you want to share it with someone who doesn't have Python installed, or you'd simply like a clean, double clickable
.exe file for your own use. This is where PyInstaller comes in, a tool that packages your Python program together with everything it needs into a single Windows executable.
In this guide you'll learn how to install PyInstaller, convert a simple script into an EXE, customize the output, and troubleshoot the errors beginners run into most often.
What You Will Need
- Python installed on Windows (Python 3.7 or higher recommended)
- A Python script you want to convert
- Basic familiarity with the command line
Step 1: Install PyInstaller
Open Command Prompt or PowerShell and install PyInstaller using pip.
pip install pyinstallerOnce installed, confirm it's working by checking the version.
pyinstaller --versionIf this command returns a version number, you're ready to go.
Step 2: Create a Simple Python Script to Convert
For this tutorial, let's use a basic example. Save the following as app.py.
# app.py
def greet_user():
name = input("What's your name? ")
print(f"Hello, {name}! This is your Python app running as an EXE.")
if __name__ == "__main__":
greet_user()
input("\nPress Enter to exit...")Step 3: Convert the Script Into an EXE
Navigate to the folder containing app.py in your terminal, then run:
pyinstaller --onefile app.pyThe --onefile flag tells PyInstaller to bundle everything into a single .exe file rather than a folder full of supporting files, which makes it much easier to share.
Once the command finishes, you'll find a new dist folder in the same directory. Inside it is app.exe, your fully packaged Windows executable.
your_project/
├── app.py
├── build/
├── dist/
│ └── app.exe
└── app.specDouble click app.exe and it should run exactly like the original script did, without needing Python installed on the machine running it.
Step 4: Useful PyInstaller Options
PyInstaller supports several flags that let you customize how the EXE behaves and looks.
# Hide the console window (useful for GUI apps)
pyinstaller --onefile --noconsole app.py
# Add a custom icon to your EXE
pyinstaller --onefile --icon=app_icon.ico app.py
# Give the output file a specific name
pyinstaller --onefile --name MyApp app.py
# Combine multiple options together
pyinstaller --onefile --noconsole --icon=app_icon.ico --name MyApp app.pyThe --noconsole flag is important to remember. Use it for GUI applications built with something like Tkinter or PyQt, but leave it out for command line tools like the example above, since hiding the console would also hide any printed output.
Step 5: Packaging an App With External Files
If your program relies on additional files, such as images, config files, or a database, you'll need to tell PyInstaller to include them using the --add-data flag.
pyinstaller --onefile --add-data "config.json;." app.pyOn Windows, the syntax uses a semicolon to separate the source file from its destination folder inside the package. If you're working across both Windows and Mac or Linux, note that Mac and Linux use a colon instead of a semicolon in this same flag.
To access these bundled files correctly from within your script, especially when running as a packaged EXE, use this pattern:
import sys
import os
def resource_path(relative_path):
"""Get the correct path for a resource, whether running as a script or a packaged EXE."""
if hasattr(sys, '_MEIPASS'):
return os.path.join(sys._MEIPASS, relative_path)
return os.path.join(os.path.abspath("."), relative_path)
# Usage
config_path = resource_path("config.json")This handles the fact that PyInstaller extracts bundled files to a temporary folder at runtime, which is different from where your script normally looks for files.
Common Errors and How to Fix Them
"Failed to execute script" With No Further Detail
This usually means an exception occurred, but the console window closed before you could read it. Rebuild without the --noconsole flag temporarily so you can see the actual error message.
pyinstaller --onefile app.pyModuleNotFoundError After Packaging
This happens when PyInstaller doesn't automatically detect a module your script depends on, often with certain libraries that load other modules dynamically. Add the missing module explicitly using the --hidden-import flag.
pyinstaller --onefile --hidden-import=some_module app.pyThe EXE File Is Very Large
Bundled executables include a full Python interpreter plus every dependency your script imports, so file sizes of 20 to 100+ MB are normal, even for simple scripts. If size matters, consider trimming unused imports or using a virtual environment with only the packages you actually need before building.
Antivirus Software Flags the EXE
This is a common false positive with PyInstaller executables, since the packaging method it uses resembles patterns some malware also uses. Submitting the file to your antivirus vendor as a false positive, or code signing the executable, are the usual solutions.
Conclusion
Converting a Python program into a Windows EXE with PyInstaller is straightforward once you understand the core workflow: install PyInstaller, run it against your script with the flags that match your app's needs, and handle bundled files with the correct resource path pattern. From here, you can package anything from small command line utilities to full GUI applications into something anyone can run with a simple double click, no Python installation required.
Hit me with a comment!