Ich weiß nicht wie cx_Freeze arbeitet, gehe aber von aus, dass es so ähnlich ist wie bei PyInstaller. Das Programm packt Interpreter und Code in eine ausführbare Datei. Weitere Daten müssen explizit mit angegeben werden, damit diese auch in die EXE gepackt werden. Beim Ausführen des Programms wird ein temporäres Verzeichnis erstellt, in dem die Ressourcen (Code und andere Dateien) entpackt werden. Der Pfad ist rein zufällig gewählt und ändert sich bei jedem Aufruf.
Ich denke mal, dass man am besten mit importlib.ressources.files arbeitet, um den richtigen Pfad zur DB zu erfahren.
Ich habs mal mit PyInstaller getestet. So sieht das Verzeichnis aus.
Code: Alles auswählen
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 09.10.2024 10:50 ressources
-a---- 09.10.2024 10:47 199 main.py
-a---- 09.10.2024 10:34 722 main.spec
-a---- 09.10.2024 10:48 35 make_exe.bat
In ressources ist nur eine __init__.py und database.db wird beim Aufruf der __init__.py angelegt.
Das habe ich getan, bevor ich das Programm mit PyInstaller gepackt habe.
Hier die main.py:
Code: Alles auswählen
from ressources import open_database
with open_database() as db:
cursor = db.cursor()
with db:
for result in cursor.execute("SELECT * FROM foo;"):
print(result)
und in ressources/__init__.py:
Code: Alles auswählen
import sqlite3
from importlib import resources
__all__ = ("open_database", "database_file")
database_file = resources.files("ressources").joinpath("database.db")
if not database_file.exists():
import string
import random
with sqlite3.connect(database_file) as _db:
cursor = _db.cursor()
with _db:
for _ in range(100):
cursor.execute("CREATE TABLE IF NOT EXISTS foo (id integer, name string);")
cursor.execute("INSERT INTO foo VALUES (?, ?)", (random.randint(0, 255), "".join(random.choices(string.ascii_lowercase, k=10))))
def open_database() -> sqlite3.Connection:
return sqlite3.connect(database_file)
Dann erstelle ich die exe.
Das erste mal mit:
Danach habe ich die erstellte Datei main.spec bearbeitet:
Code: Alles auswählen
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[("ressources", "ressources")],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='main',
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,
)
Das Einzige, was ich geändert habe: datas=[("ressources", "ressources")],
Danach habe ich die exe erneut erstellt, aber diesmal mit der main.spec:
Getestet habe ich nur unter Windows.
In
dist wird dann die Datei main.exe erstellt. Unter Linux müsste die eine andere Endung haben.
Wenn du das auf cx_Freeze übertragen willst, musst du in Erfahrung bringen, wie du cx_Freeze dazu bekommst, Ressourcen mit in die ausführbare Datei zu packen.
Die Vorgehensweise, den richtigen Pfad zur Datenbank zu bekommen, bleibt aber gleich.
Wenn du schreiben willst, geht das nicht, da nach dem Beenden des Prozesses alle temporären Dateien gelöscht werden, auch die Datenbank.
Für sowas gibt es bekannte User-Verzeichnisse. Unter Linux ist es z.B. ~/.config, ~/.local
Unter Windows ist es %localAppData% und %AppData%. %AppData% ist im Roaming-Verzeichnis und wird via OneDrive synchronisiert, sofern man das nutzt.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server