10

So I'm running into a problem where the try: except: mechanism doesn't seem to be working correctly in python.

Here are the contents of my two files.

pytest1.py

import pytest2

class MyError( Exception ):
    def __init__( self, value ):
        self.value = value

    def __str__( self ):
        return repr( self.value )

def func1():
    raise MyError( 'This is an error' )

def func3():
    pytest2.func2()

if __name__ == '__main__':
    try:
        func3()
    except MyError, e:
        print 'I should catch here.'
    except:
        print 'Why caught here?'

pytest2.py

from pytest1 import func1

def func2():
    func1()

Executing the first file yields the following output:

$ python pytest1.py
Why caught here?

Basically, the exception isn't being caught. If I print out the exception type, it prints as <pytest1.MyError> instead of just <MyError>. I imagine that this is some weird cyclical reference thing, but it still seems like it should work.

  • Winston's solution explains the problem, you can get your code to work correctly by adding the line `from pytest1 import *` to the beginning of the main code block (`if __name__ == '__main__':`) in pytest1.py, this will change `MyError` in the namespace from `` to ``. – Andrew Clark Feb 10 '11 at 01:01

3 Answers3

9

The main python program is always imported as the module __main__.

When you import pytest2, it doesn't reuse the existing module because the originally imported module has the name __main__ not pytest2. The result is that pytest1 is run multiple times generating multiple exception classes. __main__.MyError and pytest1.MyError You end up throwing one and trying to catch the other.

So, don't try to import your main module from other modules.

Winston Ewert
  • 44,070
  • 10
  • 68
  • 83
  • Confirmed. Changing `pytest2` to `import __main__` and call `__main__.func1` makes the program behave as expected. (For some reason, `from __main__ import func1` claims that there is no `func1` to import.) – zwol Feb 10 '11 at 00:51
  • Your second form won't work because in that case pytest2 is in the middle of being imported. It hasn't yet defined func1. – Winston Ewert Feb 10 '11 at 00:52
  • Make those modules contain library code only and have a central main entry point that imports all necessary parts from the modules without specifying anything itself. – poke Feb 10 '11 at 00:57
  • Also confirmed, I ended up just creating another file to define functions and errors, and a separate file for command line. –  Feb 10 '11 at 01:02
2

This problem is caused by importing the script you are running as a module. This produces two separate copies of the module!

Another example:

module.py

import module

class Foo: pass

def test():
    print Foo
    print module.Foo
    print Foo is module.Foo

if __name__ == '__main__': test()

main_script.py

import module
if __name__ == '__main__': module.test()

Result

>python main_script.py
module.Foo
module.Foo
True

>python module.py
__main__.Foo
module.Foo
False

Running python somefile.py creates a module called __main__, not somefile, and runs the code in somefile.py in that module. This is why if __name__ == '__main__': is used to check if this file is being run as a script or imported from some other file.

Baffe Boyois
  • 2,120
  • 15
  • 15
1

... at a guess, you have a namespace problem which is producing a different exception.

Try replacing

except:
    print 'Why caught here?'

with

except Exception, e:
    print e

This may tell you more about what went wrong.

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99