If you’ve ever used Python to create an application and packaged it using PyInstaller, you might have encountered the dreaded Fatal Python error: initfsencoding when running the EXE. It’s a frustrating issue that can make your project feel like it’s stuck in limbo. The good news is, it’s not an unsolvable problem. I’ll walk you through an example of a Python script that triggers this error, explain why it happens, and provide reliable fixes. Finally, I’ll give you a practice-ready script with enhancements that are more resilient and PyInstaller-friendly.
The Original Code
Here’s a basic Python script that uses Selenium to open a web browser and visit a website. This is the original script that, when packaged using PyInstaller, led to the fatal error.
# short.py
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from time import sleep
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
import time
print("Opening...")
driver = webdriver.Chrome('chromedriver.exe')
driver.get('https://google.com')
What Happening in the Code
- The script uses Selenium WebDriver to launch a Chrome browser and navigate to
https://google.com
. - The
chromedriver.exe
is needed to interface with Chrome. - The script uses
WebDriverWait
to ensure the browser loads fully before performing actions, though it doesn’t usesleep()
as it would slow down the test unnecessarily.
When packaged with PyInstaller, it’s possible to encounter the error mentioned below.
The Fatal Python Error
Here’s the error message you might see:
Fatal Python error: initfsencoding: unable to load the file system codec
zipimport.ZipImportError: can't find module 'encodings'
What It Mean
When Python initializes, it needs to load the built-in encodings package to handle text, file paths, and string-related operations. This package is essential, and if it’s missing, Python will immediately fail with the error above. This issue occurs mainly in PyInstaller-packaged EXE files because the necessary encodings
package may not be bundled correctly.
Common Causes
- Stale or buggy PyInstaller build: Sometimes, an old or incompatible build process will not bundle everything Python needs.
- Incorrect environment variables: Python uses
PYTHONHOME
andPYTHONPATH
to find libraries. If they’re set incorrectly, it can cause Python to fail when looking for theencodings
module. - Antivirus interference: Occasionally, antivirus software might quarantine important files like
base_library.zip
, which containsencodings
. - Platform mismatch: If you build the EXE on one platform and try to run it on a different one, the build might be incompatible.
- PyInstaller missed something: In rare cases, PyInstaller might not automatically include
encodings
.
How to Fix It
Here are a few practical solutions you can try to resolve this error:
Clean Rebuild with a Fresh Virtual Environment (Recommended)
The first step to fixing this issue is ensuring your environment is clean. Rebuilding your app from scratch using a new virtual environment can help:
- Create a clean virtual environment and install the necessary tools:
python -m venv .venv
.venv\Scripts\activate # On Windows
pip install --upgrade pip wheel setuptools
pip install --upgrade pyinstaller==5.13.2 # PyInstaller version compatible with Python 3.7
pip install selenium
- Rebuild your EXE cleanly:
pyinstaller --onefile --clean short.py
- flag forces PyInstaller to rebuild everything from scratch. This eliminates any stale cache issues.
- Run the EXE from a standard folder (not from a network share).
Remove Conflicting Environment Variables
Sometimes, Python environment variables like PYTHONHOME
and PYTHONPATH
can cause issues. You can temporarily remove them from the terminal before running the EXE:
set PYTHONHOME=
set PYTHONPATH=
This clears the variables and allows the Python runtime to find its libraries correctly. If the variables are set globally (system-wide), you’ll need to disable them through System Properties → Environment Variables.
Explicitly Include the encodings
Module in the Build
If the issue persists, try explicitly telling PyInstaller to include encodings
during the build process:
pyinstaller --onefile --clean --hidden-import encodings short.py
This ensures that PyInstaller bundles the necessary encodings
package with your EXE.
Check for Antivirus or Endpoint Protection Interference
Some antivirus software might mistakenly block or quarantine the base_library.zip
file or other critical resources in your build. Whitelist your build directory or temporarily disable antivirus software while building and running the EXE.
Reinstall or Repair Python 3.7
If your Python installation is broken or missing important files, repairing it could help resolve the issue. You can repair Python through the official installer:
- Download the installer for Python 3.7 from python.org.
- Run the installer and select the Repair option.
- Rebuild the EXE using the steps outlined above.
A Sturdier, Practice Ready Script
Once you’ve addressed the fatal error, it’s time to improve the script. Here’s an updated version of your script that not only avoids the sleep()
function but also improves handling for timeouts and makes the script more robust and PyInstaller-friendly.
Key Improvements:
- Chromedriver location: It now automatically locates
chromedriver.exe
, whether the script is run as an EXE or a standard Python script. - WebDriverWait: Replaces
sleep()
with more efficient waiting mechanisms. - Google search functionality: The script can search for a query and print out the top results.
Here’s the updated code:
import os
import sys
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def resource_path(rel_path: str) -> str:
base = getattr(sys, "_MEIPASS", os.path.abspath("."))
return os.path.join(base, rel_path)
def find_chromedriver() -> str:
candidates = [
resource_path("chromedriver.exe"),
os.path.join(os.getcwd(), "chromedriver.exe"),
]
for c in candidates:
if os.path.exists(c):
return c
raise FileNotFoundError("chromedriver.exe not found.")
def main(query: str = "Selenium WebDriver"):
print("Starting Chrome…")
driver_path = find_chromedriver()
service = Service(executable_path=driver_path)
driver = webdriver.Chrome(service=service)
wait = WebDriverWait(driver, 20)
try:
driver.get("https://www.google.com")
box = wait.until(EC.presence_of_element_located((By.NAME, "q")))
box.clear()
box.send_keys(query)
box.send_keys(Keys.ENTER)
results = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "h3")))
print(f"Top {min(5, len(results))} results for: {query}")
for i, h3 in enumerate(results[:5], start=1):
title = h3.text.strip() or "(no title)"
print(f"{i}. {title}")
out_path = Path.cwd() / "google_results.png"
driver.save_screenshot(str(out_path))
print(f"Saved screenshot to: {out_path}")
except Exception as e:
print(f"Error: {e}")
finally:
driver.quit()
print("Done.")
if __name__ == "__main__":
q = "Selenium WebDriver"
if len(sys.argv) > 1:
q = " ".join(sys.argv[1:])
main(q)
Building the Script with PyInstaller
For this enhanced script, you’ll need to make sure chromedriver.exe
is correctly bundled with the EXE. Use the following PyInstaller commands:
Option 1 (Folder build):
pyinstaller --clean --add-binary "chromedriver.exe;." short_plus.py
Option 2 (Onefile build):
pyinstaller --onefile --clean --add-binary "chromedriver.exe;." short_plus.py
If you still encounter the encodings
error, use this command to force the inclusion of encodings
:
pyinstaller --onefile --clean --hidden-import encodings --add-binary "chromedriver.exe;." short_plus.py
Final Thought
Dealing with fatal errors like initfsencoding
can be frustrating, but with the right fixes, it’s a solvable problem. In most cases, using a clean virtual environment, resetting environment variables, and explicitly including missing imports will do the trick. By following the steps outlined in this article, you should be able to resolve the issue and create a more robust, user-friendly script.