Making persistent changes to code per each time it runs?

Im not sure this is possible, but say I was making a program that tells you how many times its been run. The code would look something like:

times_run = 0

if __name__ == "__main__":
    times_run += 1
    print(times_run)
    exit()

which is fairly simple. But the issues is that the change isn't persistent, so the next time it's run, it would put times_run at 1 instead of the desired 2. Does anyone have some resources on learning something like this?

11 comments · 87% upvoted · other discussions

comments

wintermute93

As an inelegant but straightforward workaround, you can read/write that value to a text file elsewhere on your computer (probably the same directory where your script is or a subfolder).

japherwocky

Yes! Time to learn about how to persist data to disk!

billsil

If it’s with qt, they give you easy access to the registry. The registry is nice in that users tend to not mess with it. I store things like preferences (e.g., background color) and recent files there. I also store the window shape and location.

discreteAndDiscreet

Maybe look into pickle.

tangerinelion

Another way is to write an event to a database and query the database to get the answer.

A bad idea, but you could instead write a script to write a new version of the script, which that script calls when it is executed. This is generally a huge security problem.

MonkeyPanls

I feel like there's a Quine buried in here somewhere.

NovateI [OP]

Definite possibility

cipher315

Even if you can find a way to do this you should not. Any data that needs to be stored after a program completes should be saved to disk. A plain text file would be best for something trivial like this. Your "times_run" function would look something like this:

from pathlib import Path
@staticmethod
def run_counter():
    times_run = 0
    my_file = Path("/path/to/file")
    if my_file.is_file():
        with open("/path/to/file", "r") as file:
            times_run = file.read()
        times_run = int(times_run)
        times_run += 1
        print(times_run)
        with open("/path/to/file", "w") as file:
            file.write(str(times_run))
    else:
        with open("/path/to/file", "w") as file:
            times_run += 1
            print(times_run)
            file.write(str(times_run))

EDIT: forgot to cast stuff EDIT 2: This is probably better as a static method

fernly

It's a bad idea to store changing data in the program file. Consider if you want to share the program, give a copy to someone else. What you distribute would contain your run-count, but that user wants their own. Or, if you have to restore from backup, you lose some counts.

But having a data file brings its own problems.

  • What does the program do if the data file isn't there? You need a try/except around the file open, and if the open fails because the file isn't there, you have to create the file initialized to zero. But creating a file can fail, for example if the user doesn't have write privilege for the directory the script is in. So you need another try/except to look for that problem.

  • Where do you put the file? You need to be able to know its path at run-time. You can use the path prefix of __file__ which is where your script lives, but is it legit to create a file at that path? You could put it in the user's current dir (os.getcwd()) but that relies on the user always starting the script from the same current dir, very restrictive, and if they don't, then the file won't be there, see above. You can require the user of your code to tell you, e.g. with an environment variable, or you can write the file into the user's home dir (os.path.expanduser) but not everyone appreciates that, even if you make it hidden (os.chflags(stat.UF_HIDDEN)).

  • What is the format of the file? For your example, it's just an int encoded as a string. But you will soon want to save other good stuff, and you don't want to invent your own syntax for it. You probably want to use the config syntax of .ini files, using the configparser module. But some people would say use JSON.

(edit: add cwd option)

jjbugman2468

I’d say maybe save and export the value to an external text file, then read it in every time.