31

I want to keep & use the error value of an exception in both Python 2.5, 2.7 and 3.2.

In Python 2.5 and 2.7 (but not 3.x), this works:

try:
    print(10 * (1/0))
except ZeroDivisionError,  error:       # old skool
    print("Yep, error caught:", error)

In Python 2.7 and 3.2 (but not in 2.5), this works:

try:
    print(10 * (1/0))
except (ZeroDivisionError) as error:    # 'as' is needed by Python 3
    print("Yep, error caught:", error)

Is there any code for this purpose that works in both 2.5, 2.7 and 3.2?

Thanks

Lion
  • 18,729
  • 22
  • 80
  • 110
superkoning
  • 914
  • 2
  • 8
  • 12
  • Can you not upgrade your 2.5 code to at least 2.7 and preferably 3? – Ben Jul 01 '12 at 20:35
  • `except (ZeroDivisionError) as error: ` works fine in python 2.7 http://ideone.com/KfHBs – Ashwini Chaudhary Jul 01 '12 at 20:35
  • 2
    Python 3 is expressly not backwards compatible. Why restrict yourself to a limited subset of syntax that both languages support? – Cameron Jul 01 '12 at 20:40
  • @Ben (and Cameron) The code is used on appliances (often with Python 2.5) and on Linux installation (with Python 3.x on the horizon). Therefore both 2.5 and 3.x should work .... *If* I must choose, it will be 2.x code; that will work on on all installations: appliances *and* Linux installations. – superkoning Jul 01 '12 at 20:48
  • 2
    @AshwiniChaudhary Indeed. That's what I already said in my post. Python 2.7 looks like a fine hybrid: accepting both 2.x and 3.x style python code. It's about 2.5 versus 3.x ... – superkoning Jul 01 '12 at 20:49
  • It is impossible at large. Python 3 is not backwards compatible with respect to lots of various operation. If you cannot upgrade appliances, you should have python 2.5 running on Linux. If you use Linux installation for testing, it really *should* run the same python line as the appliance. – Piotr Kalinowski Jul 01 '12 at 20:51
  • Still an issue in 2023. You can just tell the developers of Python are completely green and have not lived in the REAL WORLD for long. The real world is an imperfect one, with lots of (isolated, private) old stuff still laying around. Having to maintain two codebases because ONE FREAKING "except" LINE IS NOT COMPATIBLE with both Python 2.5 and Python 3.x is beyond frustrating. It would have been super easy to avoid in the first place, if the Python developers had any common sense about what actually happens in the REAL WORLD. Not everyone wants to be on the bleeding edge. With good reasons. – Zizzyzizzy Aug 03 '23 at 18:09
  • ChatGPT FTW! import sys class ExceptionContextManager(object): def __enter__(self): pass def __exit__(self, exc_type, exc_value, traceback): if exc_type is not None and exc_type == ValueError: if sys.version_info.major == 2: # Exception handling for Python 2 print("Python 2 exception handling:", exc_value) elif sys.version_info.major == 3: # Exception handling for Python 3 print("Python 3 exception handling:", exc_value) return True – Zizzyzizzy Aug 03 '23 at 18:28
  • # Usage example: try: # Some code that may raise an exception result = int("not_an_integer") except ValueError: with ExceptionContextManager(): raise – Zizzyzizzy Aug 03 '23 at 18:28

1 Answers1

41

You can use one code base on Pythons 2.5 through 3.2, but it isn't easy. You can take a look at coverage.py, which runs on 2.3 through 3.3 with a single code base.

The way to catch an exception and get a reference to the exception that works in all of them is this:

except ValueError:
    _, err, _ = sys.exc_info()
    #.. use err...

This is equivalent to:

except ValueError as err:
    #.. use err...
Ned Batchelder
  • 364,293
  • 75
  • 561
  • 662
  • 1
    Granted it works, but maybe the cure is worse (uglier) than the problem. Another way would be using "as" and a code conversion script when packaging code for 2.5. YMMV. – Jürgen Strobel Sep 13 '12 at 10:04
  • The problem is that python does significant and unnecesary changes to its syntax between versions. Imagine this in C: from version x.y you use "@" instead of "{" :) This is plain stupid and the cure is much better - after all we all want it to just work! – Terminus Sep 11 '14 at 12:34
  • 1
    @Terminus Think of changes from Python 2 to Python 3 as analogous to the [change in syntax of function declarations](http://stackoverflow.com/a/22516/2738262) from first edition K&R C to ANSI C. C89/C90 accepts both syntaxes, as Python 2.7 does. – Damian Yerrick Jan 11 '15 at 15:34
  • 1
    The difference is that no one uses K&R now and no one used it shortly after introduction of ANSI. Python 3 was introduced years and years ago and people still use 2.7. So, the solution presented here is excellent - it supports all commonly used versions. And if it's ugly? That's not my problem, i want it to WORK. – Terminus Feb 26 '15 at 11:44
  • Is there any reason to prefer `_, err, _` over just `err = sys.exc_info()[1]` ? – Peter Gibson Jan 05 '17 at 03:51
  • No, just preference. – Ned Batchelder Jan 05 '17 at 12:07
  • 1
    Unfortunately for the purposes of this answer, the coverage.py link has since been updated to python2.6 and later syntax. This is a link to an older commit: https://bitbucket.org/ned/coveragepy/src/d6065d90c0a0a6100e30f7573d83b792d245fede/coverage/execfile.py?at=default&fileviewer=file-view-default – Robert Boehne Dec 12 '17 at 16:54