Peter Petocz
Peter Petocz

Reputation: 196

Data file saved only temporarily when using Pyinstaller executable

I have created an application with PyQt5 and bundled it using Pyinstaller. The application loads login info from a login.properties file that is stored in the same directory as the .py file that starts the app.

As suggested here I am modifying the path with the following function:

import os, sys
# Translate asset paths to useable format for PyInstaller

def resource_path(relative_path):
  if hasattr(sys, '_MEIPASS'):
      return os.path.join(sys._MEIPASS, relative_path)
  return os.path.join(os.path.abspath('.'), relative_path)

What it causes, is that it creates a temporary folder called _MEIPASS, that contains the files, like my login.properties.

In the app, I want to save the login.properties info with the following function:

self.loginFile = resource_path('./login.properties')    

def save_login_info(self):
        config = configparser.ConfigParser()
        config.read(self.loginFile)

        pw = self.login_ui.password_lineEdit.text()
        un = self.login_ui.username_lineedit.text()
        token = self.login_ui.token_lineEdit.text()
        alias = self.login_ui.gmail_alias_lineedit_2.text()
...     
            config.set('Login', 'password', pw )
            config.set('Login', 'username', un )
            config.set('Login', 'security_token', token )
            config.set('Login', 'alias', alias)

            with open(self.loginFile, 'w') as loginfile: 
                config.write(loginfile)

            print('Login info saved')

So the changed login info is saved to the temporary file/folder and it is not saved to the 'original' file.

Any ideas how to mitigate this problem?

Upvotes: 6

Views: 1997

Answers (2)

stilManiac
stilManiac

Reputation: 464

_MEIPASS is a temporary folder, yes. The condition if hasattr(sys, '_MEIPASS') sometimes is used to know if application is running from sources or it's built.

Do not save your config files into _MEIPASS folder. It's a good practise to create your app's folder at users directory. If you run dev version (from sources), create a file at sources directory, otherwise at users directory.

def get_config_path():
    if hasattr(sys, "_MEIPASS"):
        abs_home = os.path.abspath(os.path.expanduser("~"))
        abs_dir_app = os.path.join(abs_home, f".my_app_folder")
        if not os.path.exists(abs_dir_app):
            os.mkdir(abs_dir_app)
        cfg_path = os.path.join(abs_dir_app, "login.properties")
    else:
        cfg_path = os.path.abspath(".%slogin.properties" % os.sep)
    return cfg_path

Upvotes: 2

Jay
Jay

Reputation: 132

I have had the same problem before, it seems that if you try to write or create a file in the --onefile mode the file is not saved. However this can be fixed by including the data file in the compile command:

C:\Users\user>pyinstaller myfile.py -F --add-data path/to/file/file.txt

Upvotes: -1

Related Questions