Tkinter Installer from Level 0 to Practical Deployment

In this lesson, we will learn how to create a simple desktop application using Tkinter, convert it into a standalone .exe using PyInstaller, and then package it into a proper Windows installer using Inno Setup.

This lesson starts from absolute beginner level and moves step by step toward a practical deployment workflow.

Python GUI Tkinter PyInstaller Inno Setup Windows Installer

1. What do we mean by a Tkinter installer?

When someone says "create a Tkinter installer", they usually mean:

  1. Create a desktop GUI program using Tkinter.
  2. Convert that program into an executable file.
  3. Create a setup file that installs the program on another computer.
Important idea
Tkinter itself creates the GUI application. It does not create the installer. For the installer, we use additional tools such as PyInstaller and Inno Setup.

The full journey

1
Write Tkinter App

Create and test your Python GUI application.

2
Build EXE

Use PyInstaller to convert the Python app into a standalone executable.

3
Create Installer

Use Inno Setup to create a real installable setup file.

Why do we need this?

Suppose you built a Tkinter application on your computer. It may run because your system already has:

  • Python installed
  • required libraries installed
  • your source files in the right folders

But another person may not have Python at all. So you cannot expect them to run your app.py directly. That is why we create a packaged application and then an installer.

2. The complete workflow

Let us understand the whole process before writing code.

Stage Tool Purpose
Build the GUI Tkinter Create the visual desktop application in Python.
Package the app PyInstaller Convert Python code into a standalone EXE.
Create the installer Inno Setup Create a Windows setup file that installs the application.
Think of it like this
Tkinter gives you the car. PyInstaller makes it road-ready. Inno Setup gives it a showroom delivery system.

Folder structure

A simple project folder may look like this:

tkinter-installer-demo/
│
├── app.py
├── assets/
│   └── app.ico
├── build/
├── dist/
└── installer.iss

At the beginning, you only need:

tkinter-installer-demo/
├── app.py
└── assets/
    └── app.ico

3. Build the Tkinter application

We start with a very simple Tkinter application. This is the real application that the user will eventually install.

Basic Tkinter app

import tkinter as tk
from tkinter import messagebox

def say_hello():
    name = name_var.get().strip()
    if not name:
        messagebox.showwarning("Missing Name", "Please enter your name.")
        return
    messagebox.showinfo("Welcome", f"Hello, {name}! Your app is working.")

root = tk.Tk()
root.title("Tkinter Installer Demo")
root.geometry("500x300")
root.resizable(False, False)

title_label = tk.Label(root, text="Tkinter Installer Demo", font=("Arial", 18, "bold"))
title_label.pack(pady=20)

desc_label = tk.Label(
    root,
    text="This desktop app will later be packaged as an installer.",
    font=("Arial", 11)
)
desc_label.pack(pady=10)

name_var = tk.StringVar()

entry = tk.Entry(root, textvariable=name_var, font=("Arial", 12), width=30)
entry.pack(pady=10)

button = tk.Button(root, text="Click Me", command=say_hello, font=("Arial", 12), width=15)
button.pack(pady=20)

root.mainloop()

How this works

  • import tkinter as tk imports Tkinter.
  • from tkinter import messagebox imports popup message boxes.
  • tk.Tk() creates the main window.
  • Label, Entry, and Button create UI controls.
  • root.mainloop() starts the event loop.
Rule
First make sure the Tkinter program itself runs perfectly. Only then should you package it.

Run it

python app.py

If the app opens and works, then your first stage is complete.

A slightly more practical version

Let us make a version that stores user settings into a file. This makes the app feel more real.

import tkinter as tk
from tkinter import messagebox
import json
import os

APP_FOLDER = os.path.join(os.path.expanduser("~"), "TkinterInstallerDemo")
SETTINGS_FILE = os.path.join(APP_FOLDER, "settings.json")

def save_settings():
    username = username_var.get().strip()
    theme = theme_var.get()

    if not username:
        messagebox.showerror("Error", "Please enter a username.")
        return

    os.makedirs(APP_FOLDER, exist_ok=True)

    data = {
        "username": username,
        "theme": theme
    }

    with open(SETTINGS_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2)

    messagebox.showinfo("Saved", f"Settings saved to:\\n{SETTINGS_FILE}")

root = tk.Tk()
root.title("Settings App")
root.geometry("420x240")

tk.Label(root, text="Username", font=("Arial", 11)).pack(pady=(20, 5))
username_var = tk.StringVar()
tk.Entry(root, textvariable=username_var, width=30, font=("Arial", 11)).pack()

tk.Label(root, text="Theme", font=("Arial", 11)).pack(pady=(15, 5))
theme_var = tk.StringVar(value="Light")
tk.OptionMenu(root, theme_var, "Light", "Dark", "Classic").pack()

tk.Button(root, text="Save Settings", command=save_settings, width=18).pack(pady=25)

root.mainloop()

4. Convert the Tkinter app into an EXE with PyInstaller

Tkinter gives you the app source code, but most end users do not want to run Python files directly. They usually want a normal Windows program.

Install PyInstaller

pip install pyinstaller

Build a windowed EXE

pyinstaller --onefile --windowed app.py

Meaning of these options

Option Meaning
--onefile Create one single EXE file.
--windowed Hide the console window for GUI apps.
app.py Your main Python file.

Where does the EXE appear?

After the build finishes, look inside the dist folder.

dist/
└── app.exe

Adding an icon

pyinstaller --onefile --windowed --icon=assets/app.ico app.py

This command adds a custom icon to your program.

If your app uses images or extra files

When you run source code directly, normal relative paths often work. But after packaging, they may fail.

Bad direct usage:

logo_path = "assets/logo.png"

Better approach:

import os
import sys

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except AttributeError:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

Then use it like this:

logo_path = resource_path("assets/logo.png")

Add data files while building

pyinstaller --onefile --windowed --add-data "assets;assets" app.py
Why this matters
If your program uses images, templates, sounds, or other data files, you must make sure they are included in the packaged build.

Onefile vs onedir

Mode What you get When to use
--onefile One EXE Easy distribution
--onedir A folder with many files Easier debugging, sometimes more reliable

5. Create the Windows installer with Inno Setup

After PyInstaller gives us a standalone EXE, we use Inno Setup to create a proper installer.

What does the installer do?

  • Copies files into the installation folder
  • Creates Start Menu shortcuts
  • Optionally creates a desktop shortcut
  • Adds uninstall support
  • Can launch the app after installation

Create installer.iss

[Setup]
AppName=Tkinter Installer Demo
AppVersion=1.0
DefaultDirName={autopf}\TkinterInstallerDemo
DefaultGroupName=Tkinter Installer Demo
OutputDir=output
OutputBaseFilename=TkinterInstallerDemoSetup
Compression=lzma
SolidCompression=yes
SetupIconFile=assets\app.ico

[Files]
Source: "dist\app.exe"; DestDir: "{app}"; Flags: ignoreversion

[Icons]
Name: "{group}\Tkinter Installer Demo"; Filename: "{app}\app.exe"
Name: "{autodesktop}\Tkinter Installer Demo"; Filename: "{app}\app.exe"; Tasks: desktopicon

[Tasks]
Name: "desktopicon"; Description: "Create a desktop shortcut"; GroupDescription: "Additional icons:"

[Run]
Filename: "{app}\app.exe"; Description: "Launch Tkinter Installer Demo"; Flags: nowait postinstall skipifsilent

Understand each section

[Setup]

This section defines installer-level details such as application name, version, output file, default installation folder, and compression options.

[Files]

This section tells Inno Setup which files to copy into the installation directory.

[Icons]

This section creates Start Menu and desktop shortcuts.

[Tasks]

This defines optional items such as the desktop shortcut checkbox.

[Run]

This lets the user run the program immediately after installation finishes.

Compile the installer

  1. Install Inno Setup.
  2. Open the file installer.iss.
  3. Compile it.
  4. Look inside the output folder.
output/
└── TkinterInstallerDemoSetup.exe
Result
This setup EXE is what you share with users.

6. Complete practical example

Complete app.py

import tkinter as tk
from tkinter import messagebox
import json
import os
import sys

def resource_path(relative_path):
    try:
        base_path = sys._MEIPASS
    except AttributeError:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)

APP_FOLDER = os.path.join(os.path.expanduser("~"), "TkinterInstallerDemo")
SETTINGS_FILE = os.path.join(APP_FOLDER, "settings.json")

def save_settings():
    username = username_var.get().strip()
    theme = theme_var.get()

    if not username:
        messagebox.showerror("Error", "Please enter a username.")
        return

    os.makedirs(APP_FOLDER, exist_ok=True)

    data = {
        "username": username,
        "theme": theme
    }

    with open(SETTINGS_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2)

    messagebox.showinfo("Saved", f"Settings saved to:\\n{SETTINGS_FILE}")

root = tk.Tk()
root.title("Tkinter Installer Demo")
root.geometry("500x320")
root.resizable(False, False)

title_label = tk.Label(root, text="Tkinter Installer Demo", font=("Arial", 18, "bold"))
title_label.pack(pady=20)

tk.Label(root, text="Username", font=("Arial", 11)).pack(pady=(6, 5))
username_var = tk.StringVar()
tk.Entry(root, textvariable=username_var, width=30, font=("Arial", 11)).pack()

tk.Label(root, text="Theme", font=("Arial", 11)).pack(pady=(15, 5))
theme_var = tk.StringVar(value="Light")
tk.OptionMenu(root, theme_var, "Light", "Dark", "Classic").pack()

tk.Button(root, text="Save Settings", command=save_settings, width=18).pack(pady=25)

root.mainloop()

Build command

pyinstaller --onefile --windowed --icon=assets/app.ico app.py

Complete installer.iss

[Setup]
AppName=Tkinter Installer Demo
AppVersion=1.0
DefaultDirName={autopf}\TkinterInstallerDemo
DefaultGroupName=Tkinter Installer Demo
OutputDir=output
OutputBaseFilename=TkinterInstallerDemoSetup
Compression=lzma
SolidCompression=yes
SetupIconFile=assets\app.ico

[Files]
Source: "dist\app.exe"; DestDir: "{app}"; Flags: ignoreversion

[Icons]
Name: "{group}\Tkinter Installer Demo"; Filename: "{app}\app.exe"
Name: "{autodesktop}\Tkinter Installer Demo"; Filename: "{app}\app.exe"; Tasks: desktopicon

[Tasks]
Name: "desktopicon"; Description: "Create a desktop shortcut"; GroupDescription: "Additional icons:"

[Run]
Filename: "{app}\app.exe"; Description: "Launch Tkinter Installer Demo"; Flags: nowait postinstall skipifsilent

From source code to installable setup

  1. Write app.py.
  2. Test with python app.py.
  3. Build EXE with PyInstaller.
  4. Create installer.iss.
  5. Compile it in Inno Setup.
  6. Distribute the setup EXE.

7. Common problems and solutions

Problem 1: EXE opens and closes immediately

Cause: hidden error, missing dependency, or file path problem.

Fix: build without --windowed first so you can see the error.

pyinstaller --onefile app.py

Problem 2: Images are missing

Cause: relative path fails after packaging.

Fix: use resource_path() and --add-data.

Problem 3: Installer works but app crashes

Cause: the packaged EXE itself was already broken.

Fix: run the EXE directly from the dist folder before creating the installer.

Problem 4: Antivirus warning

This can sometimes happen with packaged executables. Test carefully, avoid suspicious bundling behavior, and distribute only well-tested builds.

Problem 5: User settings fail to save

Check whether your application has permission to write files to the chosen folder. Saving inside the user's home directory is usually a safer choice than saving inside the program installation folder.

Very important
Do not try to save user-generated data inside Program Files unless you know exactly what you are doing. Modern Windows permissions may block that.

8. Practice exercises

Exercise 1

Create a Tkinter app with:

  • one label
  • one text box
  • one button
  • one message box

Exercise 2

Convert it into an EXE using:

pyinstaller --onefile --windowed app.py

Exercise 3

Create an Inno Setup script that:

  • installs the EXE
  • creates a Start Menu shortcut
  • optionally creates a desktop shortcut

Exercise 4

Add an icon and version number to both the application and the installer.

Exercise 5

Modify the settings app so that it stores:

  • username
  • theme
  • font size
  • window width

Quick Summary

  • Tkinter builds the GUI app.
  • PyInstaller converts it into an EXE.
  • Inno Setup creates the installer.
  • Always test the EXE before making the installer.
  • Use safe file paths for user data.

Essential commands

python app.py

pip install pyinstaller

pyinstaller --onefile --windowed app.py

pyinstaller --onefile --windowed --icon=assets/app.ico app.py

pyinstaller --onefile --windowed --add-data "assets;assets" app.py

Interview Questions

Why not distribute raw Python files?

Because the target computer may not have Python or the required libraries installed.

Why use --windowed?

Because GUI apps usually do not need a console window.

Why use Inno Setup after PyInstaller?

Because PyInstaller creates the runnable application, while Inno Setup creates the installation experience.

What is the role of resource_path()?

It helps your packaged application find bundled files correctly.

MCQ Quiz

1. Which tool is used to build the GUI in this workflow?

2. Which tool creates the EXE from Python code?

3. Which tool is used to create the Windows setup installer?

4. What does --onefile do?

5. Why should you test the EXE before building the installer?

Mini assignment

Build a Tkinter installer project for a small app called Student Notes Manager.

  • Create a GUI with student name and notes.
  • Save notes to a local JSON file.
  • Build a standalone EXE.
  • Create an installer with desktop shortcut.
  • Write the exact commands you used.

9. Final conclusion

A Tkinter installer is not a single tool or a single button. It is a process.

First
Create the Tkinter app properly.
Second
Convert it into a standalone program using PyInstaller.
Third
Wrap it into a user-friendly setup package using Inno Setup.
Always
Test every stage before moving to the next stage.

Once you understand this workflow, you can build installers for many kinds of Python desktop apps, not just Tkinter.