Adding Version Information to a PyInstaller Onefile Executable


If you’ve ever created a standalone Windows executable using PyInstaller, you might have noticed that your .exe
file lacks version details like File Description, Product Name, or Company Info. While it works perfectly fine, it looks unpolished and unbranded — especially if you’re shipping your app to clients or distributing it publicly.
In this article, you’ll learn how to embed version information into your one-file executable built with PyInstaller. This is a small detail that goes a long way in giving your app a professional edge.
Why Add Version Info to Your EXE?
When a user right-clicks your .exe
and selects Properties → Details, Windows shows metadata like:
This same metadata also appears as a small tool-tip when the user hovers over the .exe
file in File Explorer, giving your application a polished and professional touch.
Note: In this guide, we’ll focus specifically on adding version information to a one-file executable. If you’re not familiar with creating an
.exe
file using PyInstaller, be sure to check out the following guide first to get started.
Prerequisites
Before we dive in, make sure you have the following:
Python installed
PyInstaller installed (Run
pip install pyinstaller
if you haven’t already)Your main Python script ready
But What Does the Version File Look Like?
At this point, you might be wondering: “Okay, I can add a version info file… but what exactly does that file look like? Is it just plain text? Does it involve some kind of programming language?”
Great questions!
Let’s start by looking at a real-world example — a Windows .exe
that already contains version information. This will give us a clear idea of what the version file should look like.
Extracting Version Info from cmd.exe
We’ll use PyInstaller’s handy tool pyi-grab_version
to extract version information from a well-known Windows executable like cmd.exe
. Run the following command in your terminal or by opening cmd window:
pyi-grab_version C:\Windows\System32\cmd.exe
This will generate a file_version_info.txt
file containing all the embedded metadata. The file will be saved in your current working directory (where the terminal or command prompt was opened).
So in my case, the generated version info file — file_version_info.txt
— was saved to:
C:\Users\RUMI
with the following content.
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(10, 0, 19041, 4355),
prodvers=(10, 0, 19041, 4355),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
flags=0x0,
# The operating system for which this file was designed.
# 0x4 - NT and there is no need to change it.
OS=0x40004,
# The general type of file.
# 0x1 - the file is an application.
fileType=0x1,
# The function of the file.
# 0x0 - the function is not defined for this fileType
subtype=0x0,
# Creation date and time stamp.
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904B0',
[StringStruct('CompanyName', 'Microsoft Corporation'),
StringStruct('FileDescription', 'Windows Command Processor'),
StringStruct('FileVersion', '10.0.19041.4355 (WinBuild.160101.0800)'),
StringStruct('InternalName', 'cmd'),
StringStruct('LegalCopyright', '© Microsoft Corporation. All rights reserved.'),
StringStruct('OriginalFilename', 'Cmd.Exe'),
StringStruct('ProductName', 'Microsoft® Windows® Operating System'),
StringStruct('ProductVersion', '10.0.19041.4355')])
]),
VarFileInfo([VarStruct('Translation', [1033, 1200])])
]
)
This is the version file we’ll use (and modify) to embed metadata into our own Python .exe
. As you can see, it’s not too difficult to understand — many fields are self-explanatory, and some even come with helpful comments.
Good news: you don’t need to fill out or modify every single field. Being a smart developer, we’ll take the generated file_version_info.txt
, copy it, and then customize only the parts that matter for our app.
Adding Version Info to Our App
Let’s say our application is called unify.exe
. At this point, your folder structure might look like this:
So, we have added version.txt
file with the following content:
# UTF-8
#
# For more details about fixed file info 'ffi' see:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
# Set not needed items to zero 0.
filevers=(1, 0, 0, 0),
prodvers=(1, 0, 0, 0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x3f,
# Contains a bitmask that specifies the Boolean attributes of the file.
flags=0x0,
# The operating system for which this file was designed.
# 0x4 - NT and there is no need to change it.
OS=0x40004,
# The general type of file.
# 0x1 - the file is an application.
fileType=0x1,
# The function of the file.
# 0x0 - the function is not defined for this fileType
subtype=0x0,
# Creation date and time stamp.
date=(0, 0)
),
kids=[
StringFileInfo(
[
StringTable(
'040904B0',
[StringStruct('CompanyName', 'Rumi Softs'),
StringStruct('FileDescription', 'A small tool to combine video clips.'),
StringStruct('FileVersion', '1.0.0.0'),
StringStruct('InternalName', 'unify'),
StringStruct('LegalCopyright', 'Rumi Softs. All rights reserved.'),
StringStruct('OriginalFilename', 'unify.exe'),
StringStruct('ProductName', 'Unify'),
StringStruct('ProductVersion', '1.0.0.0')])
]),
VarFileInfo([VarStruct('Translation', [1033, 1200])])
]
)
Linking the Version File
Now that we have our version.txt
file ready with the necessary content, it’s time to update our existing unify.spec
file to link it. Here’s the updated unify.spec
file:
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=["E:\\unify\\.venv\\Lib\\site-packages"],
binaries=[('E:\\unify\\ffmpeg_build\\bin\\ffmpeg.exe','bin'), ('E:\\unify\\ffmpeg_build\\bin\\ffprobe.exe','bin')],
datas=[],
hiddenimports=["easygui","tqdm"],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='unify',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['favicon.ico'],
version='version.txt'
)
The only change we made is adding the version file path at the end of the exe
tuple — nothing else was modified.
Building the Executable
With everything set, let’s build the .exe
!
Before doing that, it’s a good idea to clean up the previous build just to avoid any unexpected conflicts. So go ahead and delete the existing build/
and dist/
folders.
Now, open your terminal in the project root (where main.py
resides), and run:
pyinstaller unify.spec
After a successful build, you’ll see freshly created build/
and dist/
directories.
Navigate to the dist/
folder and locate your unify.exe
. Right-click on it → Properties → Details, and you’ll now see the version info and metadata you've added.
Conclusions
Adding version info might seem minor, but it’s one of those professional touches that elevate your app — especially in production environments or when sharing with non-technical users.
With just a few extra lines and a version file, your app transforms from “just another Python script” into a well-branded, traceable, and polished product.
Let’s Hear From You!
If you found this guide helpful, don’t forget to _share _it with fellow developers who might benefit too!
Have questions, suggestions, or ran into any issues while adding version info to your .exe
? 👇 Drop a comment below — I’d love to hear your thoughts and help you out.
Your feedback not only helps improve the content, but also supports others in the community facing the same challenges.
Thanks for reading, and happy coding! 🚀
Subscribe to my newsletter
Read articles from ARHAM RUMI directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
