是否可以将python代码与tkinter和sqlite3数据库包捆绑到exe可执行文件中
因此,我在Tkinter&Python中遇到的另一个问题是,我发现不可能将Tkinter和sqlite 3数据库中的一整套代码捆绑到一个exe文件中,以便共享。每次,我这样做,exe文件将无法正常运行。甚至这样做是可能的,还是我必须完全从SQLite3中移出是否可以将python代码与tkinter和sqlite3数据库包捆绑到exe可执行文件中,python,sqlite,tkinter,Python,Sqlite,Tkinter,因此,我在Tkinter&Python中遇到的另一个问题是,我发现不可能将Tkinter和sqlite 3数据库中的一整套代码捆绑到一个exe文件中,以便共享。每次,我这样做,exe文件将无法正常运行。甚至这样做是可能的,还是我必须完全从SQLite3中移出 # Core Packages import tkinter as tk from tkinter import * from tkinter import ttk from tkinter.scrolledtext import *
# Core Packages
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import *
import tkinter.filedialog
from tkcalendar import Calendar, DateEntry
from tkinter import messagebox
from tkintertable import TableCanvas, TableModel
from tkinter import ttk
# Database
import sqlite3
import csv
conn = sqlite3.connect('data.db')
c = conn.cursor()
def create_table():
c.execute('CREATE TABLE IF NOT EXISTS usersdata(firstname TEXT,lastname TEXT,email TEXT,age TEXT,date_of_birth TEXT,address TEXT,phonenumber REAL)')
def add_data(firstname,lastname,email,age,date_of_birth,address,phonenumber):
c.execute('INSERT INTO usersdata(firstname ,lastname ,email ,age,date_of_birth,address,phonenumber ) VALUES (?,?,?,?,?,?,?)',(firstname,lastname,email,age,date_of_birth,address,phonenumber))
conn.commit()
def view_all_users():
c.execute('SELECT * FROM usersdata')
data = c.fetchall()
# for row in data:
# print(row)
# return data
for row in data:
print(row)
tree.insert("", tk.END, values=row)
# tab2_display.insert(tk.END,data)
def view_all_details():
c.execute('SELECT * FROM usersdata')
data = c.fetchall()
# for row in data:
# print(row)
# return data
for row in data:
# print(row)
# tree.insert("", tk.END, values=row)
tab2_display.insert("",tk.END,row)
def get_single_user(firstname):
c.execute('SELECT * FROM usersdata WHERE firstname="{}"'.format(firstname))
data = c.fetchall()
# tab2_display.insert(tk.END,data)
return data
def edit_single_user(firstname,new_name):
c.execute('UPDATE usersdata SET firstname ="{}" WHERE firstname="{}"'.format(new_name,firstname
))
conn.commit()
data = c.fetchall()
return data
def delete_single_user(firstname):
c.execute('DELETE FROM usersdata WHERE firstname="{}"'.format(firstname))
conn.commit()
def view_all_data():
c.execute('SELECT * FROM usersdata')
data = c.fetchall()
# for row in data:
# print(row)
# result = [ row for row in data ]
# return result
create_table()
# Structure and Layout
window = Tk()
window.title("Registrio GUI")
window.geometry("750x450")
window.config(background='black')
style = ttk.Style(window)
style.configure('lefttab.TNotebook', tabposition='wn',)
# TAB LAYOUT
tab_control = ttk.Notebook(window,style='lefttab.TNotebook')
tab1 = ttk.Frame(tab_control)
tab2 = ttk.Frame(tab_control)
tab3 = ttk.Frame(tab_control)
tab4 = ttk.Frame(tab_control)
tab5 = ttk.Frame(tab_control)
tab6 = ttk.Frame(tab_control)
# ADD TABS TO NOTEBOOK
tab_control.add(tab1, text=f'{"Home":^20s}')
tab_control.add(tab2, text=f'{"View":^20s}')
tab_control.add(tab3, text=f'{"Search":^20s}')
tab_control.add(tab4, text=f'{"Edit":^20s}')
tab_control.add(tab5, text=f'{"Export":^20s}')
tab_control.add(tab6, text=f'{"About ":^20s}')
label1 = Label(tab1, text= 'Registrio GUI',padx=5, pady=5)
label1.grid(column=0, row=0)
label2 = Label(tab2, text= 'View',padx=5, pady=5)
label2.grid(column=0, row=0)
label3 = Label(tab3, text= 'Search',padx=5, pady=5)
label3.grid(column=0, row=0)
label4 = Label(tab4, text= 'Edit/Update',padx=5, pady=5)
label4.grid(column=0, row=0)
label5 = Label(tab5, text= 'Export',padx=5, pady=5)
label5.grid(column=0, row=0)
label6 = Label(tab6, text= 'About',padx=5, pady=5)
label6.grid(column=0, row=0)
tab_control.pack(expand=1, fill='both')
# Functions
def clear_text():
entry_fname.delete('0',END)
entry_lname.delete('0',END)
entry_email.delete('0',END)
entry_age.delete('0',END)
entry_address.delete('0',END)
entry_phone.delete('0',END)
def add_details():
firstname = str(entry_fname.get())
lastname = str(entry_lname.get())
email = str(entry_email.get())
age = str(entry_age.get())
date_of_birth = str(cal.get())
phone_number = str(entry_phone.get())
address = str(entry_address.get())
add_data(firstname,lastname,email,age,date_of_birth,address,phone_number)
result = '\nFirst Name:{},\nLast Name:{},\nEmail:{},\nAge:{},\nDate of Birth:{},\nPhone Number:{},\nAddress:{}\n'.format(firstname,lastname,email,age,date_of_birth,phone_number,address)
tab1_display.insert(tk.END,result)
messagebox.showinfo(title = "Registrio GUI", message = "Submitted to DataBase")
def clear_display_result():
tab1_display.delete('1.0',END)
def search_user_by_name():
firstname = str(entry_search.get())
result = get_single_user(firstname)
# c.execute('SELECT * FROM usersdata WHERE firstname="{}"'.format(firstname))
# data = c.fetchall()
# print(result)
tab2_display.insert(tk.END,result)
def clear_display_view():
tab2_display.delete('1.0',END)
def clear_entered_search():
entry_search.delete('0',END)
def clear_tree_view():
# tab2_display.delete('1.0',END)
tree.delete('1.0',END)
def export_as_csv():
filename = str(entry_filename.get())
myfilename = filename + '.csv'
with open(myfilename, 'w') as f:
writer = csv.writer(f)
c.execute('SELECT * FROM usersdata')
data = c.fetchall()
writer.writerow(['firstname','lastname','email','age','date_of_birth','address','phonenumber'])
writer.writerows(data)
messagebox.showinfo(title = "Registrio GUI", message = '"Exported As {}"'.format(myfilename))
def export_as_xls():
pass
# Main Home Registration
l1 = Label(tab1,text="First Name",padx=5,pady=5)
l1.grid(column=0,row=1)
fname_raw_entry = StringVar()
entry_fname = Entry(tab1,textvariable=fname_raw_entry,width=50)
entry_fname.grid(row=1,column=1)
l2 = Label(tab1,text="Last Name",padx=5,pady=5)
l2.grid(column=0,row=2)
lname_raw_entry = StringVar()
entry_lname = Entry(tab1,textvariable=lname_raw_entry,width=50)
entry_lname.grid(row=2,column=1)
l3 = Label(tab1,text="Email",padx=5,pady=5)
l3.grid(column=0,row=3)
email_raw_entry = StringVar()
entry_email = Entry(tab1,textvariable=email_raw_entry,width=50)
entry_email.grid(row=3,column=1)
l4 = Label(tab1,text="Age",padx=5,pady=5)
l4.grid(column=0,row=4)
raw_entry = IntVar()
entry_age = Entry(tab1,textvariable=raw_entry,width=50)
entry_age.grid(row=4,column=1)
l5 = Label(tab1,text="Date of Birth",padx=5,pady=5)
l5.grid(column=0,row=5)
dob_raw_entry = StringVar()
cal = DateEntry(tab1, width=30,textvariable=dob_raw_entry, background='darkblue',foreground='white', borderwidth=2, year=2010)
cal.grid(row=5,column=1,padx=10, pady=10)
l6 = Label(tab1,text="Address",padx=5,pady=5)
l6.grid(column=0,row=6)
address_raw_entry = StringVar()
entry_address = Entry(tab1,textvariable=address_raw_entry,width=50)
entry_address.grid(row=6,column=1)
l7 = Label(tab1,text="Phone Number",padx=5,pady=5)
l7.grid(column=0,row=7)
phone_raw_entry = StringVar()
entry_phone = Entry(tab1,textvariable=phone_raw_entry,width=50)
entry_phone.grid(row=7,column=1)
button1 = Button(tab1,text="Clear",width=12,bg='#03A9F4',fg='#fff',command=clear_text)
button1.grid(row=8,column=0,padx=10,pady=10)
button2 = Button(tab1,text="Add",width=12,bg='#03A9F4',fg='#fff',command=add_details)
button2.grid(row=8,column=1,padx=10,pady=10)
# Display Screen For Result
tab1_display = ScrolledText(tab1,height=5)
tab1_display.grid(row=10,column=0, columnspan=3,padx=5,pady=5)
button3 = Button(tab1,text="Clear Result",width=12,bg='#03A9F4',fg='#fff',command=clear_display_result)
button3.grid(row=12,column=1,padx=10,pady=10)
# View
# label_view1 = Label(tab2,text="Search Name",padx=5,pady=5)
# label_view1.grid(column=0,row=2)
# search_raw_entry = StringVar()
# entry_search = Entry(tab2,textvariable=search_raw_entry,width=30)
# entry_search.grid(row=2,column=1)
button_view2 = Button(tab2,text="View All",width=12,bg='#03A9F4',fg='#fff',command=view_all_users)
button_view2.grid(row=1,column=0,padx=10,pady=10)
# button_view3 = Button(tab2,text="Clear Search",width=12,bg='#03A9F4',fg='#fff',command=clear_entered_search)
# button_view3.grid(row=1,column=1,padx=10,pady=10)
# button_view4 = Button(tab2,text="Clear Results",width=12,bg='#03A9F4',fg='#fff',command=clear_tree_view)
# button_view4.grid(row=1,column=2,padx=10,pady=10)
# button_view5 = Button(tab2,text="Search",width=12,bg='#03A9F4',fg='#fff',command=search_user_by_name)
# button_view5.grid(row=2,column=2,padx=10,pady=10)
tree= ttk.Treeview(tab2, column=("column1", "column2", "column3","column4", "column5","column6", "column7"), show='headings')
tree.heading("#1", text="First Name")
tree.heading("#2", text="Last Name")
tree.heading("#3", text="")
tree.heading("#1", text="NUMBER")
tree.heading("#2", text="FIRST NAME")
tree.heading("#3", text="SURNAME")
tree.heading('#7',text="Phone Number")
tree.grid(row=10,column=0, columnspan=3,padx=5,pady=5)
# Search
label_view1 = Label(tab3,text="Search Name",padx=5,pady=5)
label_view1.grid(column=0,row=1)
search_raw_entry = StringVar()
entry_search = Entry(tab3,textvariable=search_raw_entry,width=30)
entry_search.grid(row=1,column=1)
# button_view2 = Button(tab3,text="View All",width=12,bg='#03A9F4',fg='#fff',command=view_all_details)
# button_view2.grid(row=1,column=0,padx=10,pady=10)
button_view3 = Button(tab3,text="Clear Search",width=12,bg='#03A9F4',fg='#fff',command=clear_entered_search)
button_view3.grid(row=2,column=1,padx=10,pady=10)
button_view4 = Button(tab3,text="Clear Results",width=12,bg='#03A9F4',fg='#fff',command=clear_display_view)
button_view4.grid(row=2,column=2,padx=10,pady=10)
button_view5 = Button(tab3,text="Search",width=12,bg='#03A9F4',fg='#fff',command=search_user_by_name)
button_view5.grid(row=1,column=2,padx=10,pady=10)
tab2_display = ScrolledText(tab3,height=5)
# tab2_display = Listbox(tab2,height=5,width=60)
tab2_display.grid(row=10,column=0, columnspan=3,padx=5,pady=5)
# tree= ttk.Treeview(tab3, column=("column1", "column2", "column3","column4", "column5","column6", "column7"), show='headings')
# tree.heading("#1", text="First Name")
# tree.heading("#2", text="Last Name")
# tree.heading("#3", text="")
# tree.heading("#1", text="NUMBER")
# tree.heading("#2", text="FIRST NAME")
# tree.heading("#3", text="SURNAME")
# tree.heading('#7',text="Phone Number")
# tree.grid(row=10,column=0, columnspan=3,padx=5,pady=5)
# Export Database
label_export1 = Label(tab5,text="File Name",padx=5,pady=5)
label_export1.grid(column=0,row=2)
filename_raw_entry = StringVar()
entry_filename = Entry(tab5,textvariable=filename_raw_entry,width=30)
entry_filename.grid(row=2,column=1)
button_export3 = Button(tab5,text="To CSV",width=12,bg='#03A9F4',fg='#fff',command=export_as_csv)
button_export3.grid(row=3,column=1,padx=10,pady=10)
button_export3 = Button(tab5,text="To XLS",width=12,bg='#03A9F4',fg='#fff',command=export_as_xls)
button_export3.grid(row=3,column=2,padx=10,pady=10)
data = {'rec1': {'col1': 99.88, 'col2': 108.79, 'label': 'rec1'},
'rec2': {'col1': 99.88, 'col2': 108.79, 'label': 'rec2'}
}
# data2 = view_all_data()
table = TableCanvas(tab4,data=data)
table.show()
# About TAB
about_label = Label(tab6,text="",pady=5,padx=5)
about_label.grid(column=0,row=1)
window.mainloop()
是的,完全可以使用Tkinter和SQLite创建可执行文件。为此,我通常使用
Pyinstaller
(有关详细信息,请参阅和)
在虚拟环境中安装Pyinstaller
后,应使用以下格式创建一个文件main.spec
,以便您有足够的自由来完全自定义exe文件。根据您的代码,您可能需要更少或更多的功能:
# -*- mode: python -*-
import os
block_cipher = None
current_dir = os.path.dirname(os.path.curdir)
a = Analysis(['main.py'],
# pathex=['output_path'],
pathex=[current_dir],
binaries=[],
datas=[
('img/*.png', 'img'),
('inputs/*.csv', 'inputs'),
('databases/*.db', 'databases'),
('settings.ini', '.'),
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
Tree('documentation/_build/html', prefix='documentation/_build/html/'),
name='Project Name',
debug=False,
strip=False,
upx=True,
console=False)
您应该正确设置输出路径
和项目名称
。此外,该脚本假定您的主文件名为main.py
,但您也可以对此进行更改。如您所见,在本例中,我捆绑了所有的图像、csv文件、数据库(SQLite),甚至是从Sphinx创建的文档
然后,您必须调用以下命令:
path_to_pyinstaller/pyinstaller --onefile main.spec --key your_key
其中path_to_pyinstaller
是在virtualenv下安装pyinstaller的路径。您还必须设置您的_键
也可以使用其他库,例如cx\u Freeze
,但我通常使用Pyinstaller
重要的是要记住,捆绑时,可能会出现一些与相对路径相关的错误。我的解决方案是定义一个函数resource\u path
,如下所示:
import sys
# Get the absolute path
def resource_path(relative_path):
""" Get absolute path to resource, works for dev and for PyInstaller """
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
base_path = sys._MEIPASS
except Exception as e:
# print(e)
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
然后,您应该在调用任何图像、文件或数据库时使用此函数。例如,当连接到SQLite时,您应该执行以下操作:
import sqlite3
self.conn = sqlite3.connect(resource_path(database_path))
其中,
database\u path
是数据库的相对路径。我相信我已经尝试过这种方法,但是当里面有sqlite3时,它似乎不起作用。exe文件不执行。当我单击.exe文件时,它显示尝试此操作时无法执行。它附带一个弹出窗口,说明脚本无法执行。但是,当我使用非sqlite3 python代码时,它似乎运行良好。我想,在运行我提到的命令时,应该会出现错误。也许你能给我们提供那个错误。。。。还要确保在main.spec文件的data
变量下包含所有数据库。@powerlordx1,我添加了一个重要函数,您应该调用该函数以避免出现相对/绝对路径问题。尝试在代码中调用它,看看exe是否工作。在生成exe文件时,能否提供日志?也许你也可以把它放在一个单独的问题里。。。