I built my app, which has access to some files in its folder, which it can change (rewrite). Exactly they are config.ini and save file. When I run it in VS Code everything works perfectly, and when I run it in the directory "dist" it also works perfectly. But when I made a setup file through InstallForge I got the problem. In the first run it can change these files, but in the second - no.
I tried adding directories instead of relative path and remove deleting files replacing it with rewriting them as empty, but it didn't work. I added these files in --add-data in pyinstaller, and still didn't work. When I run it second time and try to save config it crashes, and when I try to save save file it gives an error: [Errno 13] Permission Denied. The app installs itself in the Program Files x86 folder. The code of saving config in the app.py (pyqt6 app):
def save(self):
global smtp_server, port, email, password, frequency, method, server_ip, time, TIMES
email_s = self.email_line.text().strip()
password_s = self.password_line.text().strip()
smtp_server_s = self.smtp_server_line.text().strip()
port_s = self.port_chose.currentText()
frequency_s = self.check_frequency.currentIndex()
method_s = self.check_method.currentIndex()
server_ip_s = self.ip_server.currentIndex()
if email_s is None or not validate_email(email_s):
email_broken = QMessageBox(self)
email_broken.setWindowTitle("Ошибка сохранения")
email_broken.setText("Введенный email недействителен!")
email_broken.setIcon(QMessageBox.Icon.Critical)
email_broken.setWindowIcon(QIcon(LOGO))
button = email_broken.exec()
elif (password_s is None) or (password_s == "") or (password_s == " "):
password_broken = QMessageBox(self)
password_broken.setWindowTitle("Ошибка записи")
password_broken.setText("Введенный пароль недействителен!")
password_broken.setIcon(QMessageBox.Icon.Critical)
password_broken.setWindowIcon(QIcon(LOGO))
button = password_broken.exec()
elif (smtp_server_s is None) or (smtp_server_s == "") or (" " in smtp_server_s):
smtp_broken = QMessageBox(self)
smtp_broken.setWindowTitle("Ошибка записи")
smtp_broken.setText("Введенный smtp-сервер недействителен!")
smtp_broken.setIcon(QMessageBox.Icon.Critical)
smtp_broken.setWindowIcon(QIcon(LOGO))
button = smtp_broken.exec()
else:
create_config(smtp_server_s, port_s, email_s, password_s, frequency_s, method_s, server_ip_s)
smtp_server = smtp_server_s
port = int(port_s)
email = email_s
password = password_s
frequency = frequency_s
method = int(method_s)
server_ip = int(server_ip_s)
time = TIMES[frequency]
save_dialog = QMessageBox(self)
save_dialog.setWindowTitle("Сохранение настроек")
save_dialog.setText("Изменения сохранены")
save_dialog.setStandardButtons(QMessageBox.StandardButton.Ok)
save_dialog.setIcon(QMessageBox.Icon.Information)
save_dialog.setWindowIcon(QIcon(LOGO))
button = save_dialog.exec()
if button == QMessageBox.StandardButton.Ok:
pass
And the code of creating config.ini:
def create_config(server, port, login, password, frequency, method, ip_server):
global CONFIG_FILE
config = configparser.ConfigParser()
config.add_section("ACCOUNT")
config.add_section("SETTINGS")
config.set("ACCOUNT", "server", server)
config.set("ACCOUNT", "port", str(port))
config.set("ACCOUNT", "login", login)
config.set("ACCOUNT", "password", password)
config.set("SETTINGS", "frequency", str(frequency))
config.set("SETTINGS", "method", str(method))
config.set("SETTINGS", "ip_server", str(ip_server))
with open(CONFIG_FILE, "w") as config_file:
config.write(config_file)
The code of saving save file:
def create_save_file(ip, email, server):
file = open(SAVE_FILE, "w")
file.write(f"{ip}\n{email}\n{server}")
file.close()
I also declare constants of file paths:
BASEDIR = path.dirname(__file__)
CONFIG_FILE = path.join(BASEDIR, "config.ini")
SAVE_FILE = path.join(BASEDIR, "save")
os.path.expandvars('$HOME')to get user's home folder, or evenos.path.expandvars('$HOME/folder_for_your_settings')and latermkdirs()to create own folder for settings