The first obstacle on my project steeplechase was Python versions supported by QEMU. I, a kid spoiled by Python 2.7-3.x sweets, was rather discouraged by the limitation to versions 2.4-2.7. Well, for pessimists obstacles are difficulties, for optimists they are opportunities.
In this post I'll collect all ambiguities I meet during project and ways I resolve them. Also there are some notes about the state of things in Python 3.x.
I have the test runner that will execute several tests in a row. Tests are instances of Test class. The goal is to clean up work environment after each test (close files, change the current directory and so on). The ideal case for context managers!
class Test(object): def execute(self): # Run test pass def __enter__(self): return self def __exit__(self, *args): # Do cleanup pass with Test() as test: test.execute()
But their birth dated by Python 2.5. Well, let's return back to roots. Unwrap “with … as” construction to explicit setup, execution and finalization, forming last two in “try … finally” statement. Here we are!
class Test(object): def execute(self): # Run test pass def finish(self): # Do cleanup pass test = Test() try: test.execute() finally: test.finish()
But there is one little note… What if you want to catch exceptions?
A piece of cake! Even a three month child can tap by her foot
try: raise Exception except: print 'Internal error' finally: print 'Bye!'
But her mom that remembers the times of Python 2.4 would wish to correct it on the sly to
try: try: raise Exception except: print 'Internal error' finally: print 'Bye!'
Because Python 2.4 doesn't support “except” and “finally” clauses in the same “try” statement.
But she is a good mom and lets her child live in the world with less lines of code.
Another thing that is worth to keep in mind is the exception root class. Python 2.4 has Exception class as a root one. From Python 2.5 the root class is BaseException, and SystemExit, KeyboardInterrupt, GeneratorExit classes don't inherit from Exception class anymore. So a catch of “except Exception” statement depends on the python version.
The problem can be resolved by special handling of unnecessary exceptions. In my case every exception but related to the program exit should be logged.
import sys try: raise Exception # Silent exit on user break except (KeyboardInterrupt, SystemExit): sys.exit(1) except: e = sys.exc_info() print e sys.exit(1)
Hey, adepts of Universality and Portability bordering with Nerdiness, if you're going to write something Python 2.4-3.x compatible, remember the power of sys.exc_info() because reasons.
Parsing of command line arguments
This task wasn't an issue if optparse library wouldn't be deprecated since Python 2.7. Of course, there is some stability in the world and the name of this stability is
entropy “getopt”. The one point worth to be noted here is that presence of mandatory positional parameters should be checked by script itself. The library doesn't provide this option.
Oops, it looks like my keyboard are running out of ink. I will update this post as soon as I tank up my keyboard and find something exiting on this topic.
PEP 0343 The “with” statement
Python 2.4 The “try” statement
Python 2.4 Built-in exceptions