By Bundling a Python application that utilizes Tkinter for its graphical user interface and SQLite for data management into a single executable, simplifies distribution and enhances the user experience. PyInstaller is a powerful tool that facilitates this process. Below is a step-by-step guide to achieve this:
← Part I: Browse and connect to SQLite database ( without bundling )
Place our main Python script (e.g., my_sqlite_app.py) and the SQLite database file (e.g., my_db.db) in the same directory.
3. Modify the Application to Locate the Database:
When bundled, the application's directory structure changes. Adjust our code to dynamically locate the database file:
from sqlalchemy import create_engine,text
base_path = os.path.dirname(__file__) # path to current directory
db_path=os.path.join(base_path, 'my_db.db') # path to SQLite database
my_conn = create_engine("sqlite:///"+db_path).connect() # connection object
4. Bundle the Application with PyInstaller:
Use PyInstaller's --add-data option to include the SQLite database in the executable. The syntax differs between operating systems:
my_sqlite_app.py : Source code or our main file. D:\\testing\\sqlite\\my_sqlite_app.py : Full Path to our source file. D:\\testing\\sqlite\\my_db.db : Full path to our SQLite database file. D:\\my_app : Destination path where our executable file will be stored.
We will bundle one application with SQLite database where we will display records from student table. We kept both our application file my_sqlite_app.py and SQLite database my_db.db in same directory.
This is a read only application where records are only displayed.
from tkinter import ttk
import tkinter as tk
import os
# Creating tkinter window
my_w = tk.Tk()
my_w.geometry("560x280") # width and height of the window.
my_w.title("www.plus2net.com")
# Using Treeview widget
trv = ttk.Treeview(my_w, selectmode='browse')
trv.grid(row=1, column=1, padx=30, pady=20)
style = ttk.Style(my_w)
style.theme_use("clam") # set theme to clam
style.configure("Treeview", background="black",
fieldbackground="black", foreground="white")
style.configure('Treeview.Heading', background="PowderBlue")
from sqlalchemy import create_engine, text
base_path = os.path.dirname(__file__) # path to current directory
db_path = os.path.join(base_path, 'my_db.db') # path to SQLite database
my_conn = create_engine("sqlite:///" + db_path).connect() # connection object
r_set = my_conn.execute(text('SELECT * FROM student'))
l1 = [r for r in r_set.keys()] # List of column headers
r_set = [r for r in r_set]
trv['height'] = 5 # Number of rows to display, default is 10
trv['show'] = 'headings'
# column identifiers
trv["columns"] = l1
# Defining headings, other options in tree
# width of columns and alignment
for i in l1:
trv.column(i, width=100, anchor='c')
# Headings of respective columns
trv.heading(i, text=i)
## Adding data to Treeview
for dt in r_set:
v = [r for r in dt] # creating a list from each row
trv.insert("", 'end', iid=v[0], values=v) # adding row
my_w.mainloop()
Writable Databases: If the application needs to write to the database, consider copying the bundled database to a writable location (e.g., the user's home directory) upon the application's first run.
my_sqlite_app2.py : Source code or our main file. D:\\testing\\sqlite\\my_sqlite_app2.py : Full Path to our source file. D:\\testing\\sqlite\\my_db.db : Full path to our SQLite database file. D:\\my_app : Destination path where our executable file will be stored.