I need to locally store some basic data the user inputs into my exe. The program was compiled using pyinstaller and was previously making use of the os open method of saving data to txt files. It is my understanding that macOS(my OS although cross-compatibility with Windows would be great) locks executables so that they may not make any file changes. The program currently does save the data, but when the executable is run again the old data is no longer accessible.
It seems obvious that apps store things locally all the time, how can data be persisted specifically within the python/pyinstaller combination?
Apologies if this is a simple question, it definitely seems simple but I can't find documentation for this anywhere.
You can use
os.path.expanduser('~user')
to get the user home directory in a cross-platform manner, see How to find the real user home directory using python?
Your application should have write permissions in the user home directory, so then you can let it create and modify a data file there following How to store Python application data.
Related
I've built a project with Python in which a module of functions can be changed by the user. More specifically, functions can be added or deleted inside this module by other processes in the application. Now I have just converted the whole project into an executable file using auto-py-to-exe to run it through a console window, instead of running it through VS Code for instance. I can't change the module if it was not added as an additional file in auto-py-to-exe rather can the application use this module if I do add it as an additional file.
My question is: how can I turn this project into an executable with the possibility of changing this module by the program itself?
This may be tricky, but it is possible with tools like pyinstaller when you bundle your app as a directory, rather than a single file executable. The source files (albeit compiled) will be present in the directory.
In principle, you could edit files in a single-file executable, but it's probably more trouble than it's worth and may be blocked by permissions and other issues.
You could also design your software to read a file from a predefined location (or the bundle directory -- anywhere accessible by the user) and simply exec the string of the code to 'load' it. It could look more or less like an extension/scripting system for your program. One example comes to mind: the iterm2 software Python API.
It should go without saying that you must trust your users/inputs if you give them the ability to arbitrarily change the software code.
I am trying to create a google drive like backup program using python that backs up to a Linux box that will further backup to an off site place tbd. I have ran into a few interesting coding and computer challenges in doing this.
The one I am working on right now has to do with "locked" files. So what do I mean by this? In windows 7 if you create a .txt file you can open it in notepad(any program) and at the same time you can open it in a python program. If you make a change in the .txt file and save the change but BEFORE closing it you can still open and see the changes in pythn. Now change the file to a .docx windows file and open it with word 2007. While opened in word you cannot access it with in python until the user closes it.
Now if you look at google drive, the desktop install not the web only variety, you can open a .docx file and change it. Once you save it but BEFORE closing google drive has already synched the file.
Google drive must have some sort of lower level access to the file than the simple python file.open() command.
So here is the question. Does anyone know of a way to access files in python in such a way as to keep me from having to wait for the user to close the file.
Edit 1:
Let me further explain. Once I have created an sqlite database that has all the files and directories I will then use the win32file.ReadDirectoryChangesW() function to monitor for changes. My problem stems from the fact that when setting up the application of first install/run it must catalog all files and files that are open in windows office are locked and cannot be cataloged. Is there a way around this?
Many backup tools use snapshots. Then, they'll copy the locked file directly from the snapshot rather than coping it directly from the filesystem. If you're on Windows you should check Windows VSS, see the Microsoft documentation for more details. Otherwise, if the filesystem you're on supports snapshots check its documentation as well.
Third party tools
You can use the subprocess Python module to run third-party tools which will take snapshots for you.
Microsoft VSS
In case you want to do it by yourself you might need modules from the Win32 API such as win32com module.
There is also on Github a project that seems to do the job: pyshadowcopy
Filesystem Snapshot
Depending on the filesystem features, you might find python modules or tools allowing you to take a snapshot.
I recently came across an interesting way to deploy a Python application to users on a local Windows network:
Install Python properly on user machines (the same minor version on all machines)
Create a shared network folder
Copy Python application files into the folder
Create a .bat script that tweaks the PYTHONPATH and invokes the main .py file
Copy shortcut onto each Windows desktop
User invokes the application by double-clicking the shortcut
This deployment option isn't listed as a shipping option in the Python Guide. Are there any obvious gotchas to having multiple users run the same .py files from a shared location?
(Assume that any other resource sharing is handled correctly by the application(s), e.g. they don't try to write to a shared file.)
(I'm open to suggestions on making this a more valid and answerable question.)
Your creative approach requires your PC to always be on, and the network working, and what about performance, when is it safe to update python, what about someone who wants to use your app away from your network, ...
Why not package the script into an exe? I've used py2exe http://www.py2exe.org/
This has the added advantage that it's not so easy for people to play with your script and 'adapt' it in ways that might break it. The exe is a lot bigger than the script, but we're not talking hundreds of megs. It doesn't need an installer or anything like that.
I wrote a wxPython GUI where I currently configure some of the widgets and some default values by using "import data" for a module file containing several lists.
But I need to compile the whole program using py2exe for a user without a python installation.
In so doing, I lose the capability of letting the user edit the data.py file to change
those configuration defaults.
I could put each list as a series of text strings and read and parse the whole thing, but that
seems like a huge waste when python already can do all that by a simple import statement.
I could probably do it with xrc/xml or perhaps ConfigParser but it would seem there should be an easy way to sort of
import data.txt
or something similar and let python do it's thing! Then when py2exe gets hold of it it, it wouldn't create un-editable byte-code for the data.txt file.
Any suggestions?
files that are imported are bundled in the executable by py2exe. The way to go is to use a configuration file that you package with your executable in a zip or with Inno Setup. Configuration files are files made to be changed at some moment, contrarily a user should not be modifying a python script. I tell you because some 'negative' experiences to say something polite.
For my programs (practically all use wxPython GUIs) I use to have a py module with configuration data (directories, etc) and some globals. This module is used to load default parameters if the program does not find my .ini file or if that especific parameter has not been set in the ini. Then I distribute everything (exe and auxiliary files) with inno setup.
I'm working on a really simple python package for our internal use, and want to package it as a .egg file, and when it's installed/used I want it to access a text file that is placed in an appropriate place on the computer.
So where is the best place to put application data in python? (that is meant to be edited by users) How do I get my python package to automatically install a default file there?
note: I know about the Windows application data directory, but would like to avoid it, as it's nonportable and kind of cumbersome both for users to access and for my application to access.
os.path.expanduser('~')
Each OS will have it's own directory where application data is expected to exist. There does not appear to be a method that provides this path in a platform-independent manner. You can write your own function to do this for you by checking os.name and then returning the appropriate value depending on the result.