[Python] How to fix Permission Denied error in the built app by pyinstaller?

Discussão em 'Python' iniciado por Stack, Junho 18, 2025.

  1. Stack

    Stack Membro Participativo

    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")

    Continue reading...

Compartilhe esta Página