On Fri, 09 Oct 2009 23:30:16 +0000, gb345 wrote: > The following fragment is from a tiny maintenance script that, among > other things, edits itself, by rewriting the line that ends with '### > REPLACE'. > > ###################################################################### > > import re > import fileinput > > LAST_VERSION = 'VERSION 155' ### REPLACE > > service = Service(url='http://url.to.service') > > if service.version_string == LAST_VERSION: > sys.exit(0) > > for line in fileinput.input(sys.argv[0], inplace=True): > if re.search(r"### REPLACE$", line): > print ("LAST_VERSION = '%s' ### REPLACE" % > service.version_string) > else: > print line, > > # ...and goes on to do more stuff... > > ###################################################################### > > This script is meant to run periodically (via cron), and "do more stuff" > whenever the fetched value of service.version_string differs from what > it was at the time of the script's prior invocation. (The interval of > time between such changes of value varies from one change to the next, > but it is always of the order of several weeks.) > > Hence this script needs to preserve state between invocations. The > rationale for the acrobatics with fileinput above is to make this script > completely self-contained, by circumventing the need some external means > (e.g. a second file, or a DB) of preserving state between invocations. > > Is there a better way to circumvent the requirement for an external > repository of state information?
Yes -- change the requirement. What's wrong with having a separate file to store state? Self-modifying code is almost always the wrong solution, unless the problem is "how do I generate an unmaintainable mess?". But if you absolutely have to write to the program file, then append your data to the end of the file (as a comment) and later read that, rather than modifying the actual code in place. That is, you fetch the LAST_VERSION by reading the last non-empty line in the file, something like this: # Untested def get_last_version(filename): """Retrieves the last version number from the given filename, taken from the last non-empty line.""" candidate = '' for line in open(filename, 'r'): line = line.strip() if line and line.startswith('#'): candidate = line.lstrip('# \t') # error checking goes here return candidate LAST_VERSION = get_last_version(sys.argv[0]) ... more code goes here ... # ================================================== # === Version number history goes here. === # === DO NOT insert any code after this point!!! === # ================================================== # 1.0.1 # 1.0.2a # 1.0.2 # 1.0.5 This has the added advantage that you can track the updates made to the version number. -- Steven -- http://mail.python.org/mailman/listinfo/python-list