我用 Tkinter 在 python 中制作了一個 GUI。現在我只想創建一個可執行檔案(.exe),這樣任何人都可以使用我的程式。該程式必須記錄資料(目的是遵循管理指標),因此必須存盤和訪問資料。我需要能夠使用我的 exe 執行我的 CRUD(創建、讀取、更新、洗掉)。
為此,我使用 sqlite3。 當我從 VSCode 運行我的程式時: 資料保存得很好,當我關閉程式并重新運行它時,我找到了我所有的資料。一切正常。
問題: 現在,當我啟動同一個程式的 .exe 時,(我使用 auto-py-to-exe 構建 exe:我只選擇了我的 python 腳本以及我的檔案,它創建了一個 exe)。當我運行我的 exe 時,我可以保存我的資料。但是當我關閉我的 exe 并重新打開它時,我的所有資料都丟失了!
我簡化了代碼以理解問題。因此,我創建了在用戶選擇樹視圖小部件中的第 6 行時觸發的方法。這將打開一個顯示資料的新視窗。當我點擊按鈕時,新資料被保存。
我無法完整發送所有代碼,所以我只發送包含在“if chooseUser == 6”塊中的代碼。這些是基本的方法。目標是簡化問題: ? 方法生成唯一識別符號 ? 方法回傳當前日期和時間 ? 方法檢查資料庫是否已存在。如果它不存在,它會創建它。? 方法檢索資料 ? 方法根據識別符號洗掉資料 ? 方法將資料保存在 2 個表中:oa 表稱為“history”:它有 2 列:scan_id 和 date_scan o 第二個表稱為:“indica ":它有 3 列:scan_idi、data_one、data_two 這是代碼:
if choixUser ==6:
win_debug = Toplevel(newWindow, bg="black")
win_debug.geometry("480x350")
win_debug.minsize(width=480, height=350)
win_debug.maxsize(width=480, height=350)
win_debug.resizable(height = None, width = None)
win_debug.geometry(f" {root.winfo_x() 500} {root.winfo_y() 100}") #
def random_id():
b1 = random.choice(string.ascii_uppercase)
b2 = random.choice(string.ascii_uppercase)
b3 = random.randint(10000,99999)
b4 = random.choice(string.ascii_lowercase)
b5 = random.randint(10,99)
id = f"{b1}{b2}-{b3}{b4}-{b5}"
return id
def gimme_the_date_now():
date = datetime.now()
out_format = "%d/%m/%Y %H:%M:%S"
date_formatee = datetime.strftime(date, out_format)
return date_formatee
def verify_or_create_DB():
connexion= sqlite3.connect('astupiddb.db')
cursor = connexion.cursor()
command1 = """CREATE TABLE IF NOT EXISTS history(scan_id TEXT PRIMARY KEY, datescan TEXT)"""
command2 = """CREATE TABLE IF NOT EXISTS indic(scan_id TEXT, data_one TEXT, data_two DOUBLE)"""
cursor.execute(command1)
cursor.execute(command2)
def fetch_datas(table):
connexion= sqlite3.connect('astupiddb.db')
query = f"SELECT * FROM {table}"
result = pd.read_sql(query, connexion)
result = pd.DataFrame(result)
return result
def suppr_data_with_the_id(id):
connexion= sqlite3.connect('astupiddb.db')
command1 = f"""DELETE FROM history WHERE scan_id =?"""
cursor = connexion.cursor()
cursor.execute(command1, (id,))
connexion.commit()
command2 = f"""DELETE FROM indic WHERE scan_id =?"""
cursor = connexion.cursor()
cursor.execute(command2, (id,))
connexion.commit()
def send_Datas_to_DB(dataFrame1, dataFrame2):
connexion= sqlite3.connect('astupiddb.db')
dataFrame1.to_sql('history', connexion, if_exists="append", index=False)
dataFrame2.to_sql('indic', connexion, if_exists="append", index=False)
connexion.commit()
connexion.close()
def prepareData_and_store():
id_Scan = random_id()
date_Scan = gimme_the_date_now()
d1 = random.choice(string.ascii_uppercase)
d2 = random.randint(10000,99999)
DATAFRAME_ONE = pd.DataFrame(columns=["scan_id","datescan"])
DATAFRAME_ONE= DATAFRAME_ONE.append({"scan_id":id_Scan,"datescan":date_Scan},ignore_index=True)
DATAFRAME_TWO = pd.DataFrame(columns=["scan_id","data_one","data_two"])
DATAFRAME_TWO= DATAFRAME_TWO.append({"scan_id":id_Scan,"data_one":d1,"data_two":d2},ignore_index=True)
send_Datas_to_DB(DATAFRAME_ONE,DATAFRAME_TWO)
verify_or_create_DB()
columns_tree = ('scan_id','datescan','data_one','data_two')
tree = ttk.Treeview(win_debug, columns=columns_tree, show='headings', selectmode='browse')
tree.column('#1', minwidth = 80, width = 80, stretch = False)
tree.column('#2', minwidth = 80, width = 80, stretch = False)
tree.column('#3', minwidth = 80, width = 80, stretch = False)
tree.column('#4', minwidth = 80, width = 80, stretch = False)
tree.heading('scan_id', text='scan id')
tree.heading('datescan', text='datescan')
tree.heading('data_one', text='data_one')
tree.heading('data_two', text='data_two')
tree.place(x=10,y=10)
# Barre de scroll:
scrollbar = ttk.Scrollbar(win_debug, orient="vertical", command=tree.yview)
scrollbar.place(x=10 320 3, y=10, height=225 2)
tree.configure(yscroll=scrollbar.set)
result_datas = fetch_datas("history")
result_datas_2 = fetch_datas("indic")
all_datas = result_datas_2.merge(result_datas, how="left", on="scan_id")
all_datas["datescan"] = pd.to_datetime(all_datas["datescan"],format="%d/%m/%Y %H:%M:%S")
all_datas = all_datas.sort_values(by="datescan", ascending=False)
for index,row in all_datas.iterrows():
scan_id = row["scan_id"]
date_scan = row["datescan"]
data_one = row["data_one"]
data_two = row["data_two"]
# L'attribut text correspond à la colonne #0
tree.insert("", "end", values = (scan_id, date_scan, data_one,data_two))
one_button = tkinter.Button(win_debug,text="i store in the memory",command=prepareData_and_store)
one_button.place(x=330,y=250)
這是總結我的問題的影像: 在此處輸入影像描述
由于Py到exe生成的臨時檔案夾,這是我用來重新定義路徑的函式:
def path_pour_wrapExe(fichier):
# pour les versions >=1.6
if hasattr(sys, '_MEIPASS'):
chdir(sys._MEIPASS)
fichier = join(sys._MEIPASS, fichier)
# Pour les versions <1.6
elif '_MEIPASS2' in environ:
chdir(environ['_MEIPASS2'])
fichier = join(environ['_MEIPASS2'], fichier)
# Pour le développement
else:
chdir(dirname(sys.argv[0]))
fichier = join(dirname(sys.argv[0]), fichier)
return fichier
從昨天開始,我一直被這個可執行問題所困擾,一旦關閉就會丟失資料。如果我不能解決這個問題,我的程式將無法使用? 你是我最后的希望!
更新:當我選擇在一個目錄模式下構建我的 exe 時,它??可以作業。但我需要將所有內容包裝在一個唯一的 exe 檔案中!怎么辦呢?
更新:我使用了Roland Smith的解決方案,并設法將所有內容包裝在一個 exe 中:它可以作業,謝謝 Roland!這是解決臨時檔案問題的函式:
user_folder = os.environ["HOMEPATH"]
engine = create_engine(f'sqlite:///C:\{user_folder}\nameofadatabase.db',echo=True)
uj5u.com熱心網友回復:
當您使用“一個檔案”模式時PyInstaller(auto-py-to-exe前端)所做的就是將您的腳本、資料和庫打包到一個可執行程式中。
當您運行該程式時,它會將可執行檔案解壓縮到一個臨時目錄中并從那里運行您的腳本。
所以當你運行程式時,它可能會更新資料庫就好了。但是(這里我們遇到了問題)當程式關閉時,臨時目錄被洗掉,并且可執行檔案沒有使用臨時檔案夾的任何修改內容進行更新。
編輯:
我看到兩種可能的解決方案:
請改用“一個檔案夾”打包方法。您將檔案夾作為 ZIP 檔案提供給用戶。用戶將 ZIP 檔案解壓縮到一個檔案夾中并從該檔案夾啟動程式。這解決了問題,因為檔案夾在每次使用后都不會被洗掉。所以任何修改過的資料庫檔案都將保留。
如果您仍想使用“一個檔案”方法,請在用戶的主目錄中創建并保存資料庫。(應該
os.environ["HOMEPATH"]在 ms-windows 上。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/492984.html
標籤:Python sqlite tkinter 可执行程序 在记忆中
