views:

391

answers:

2

I have two modules, main and notmain. I declared my custom exception in main module and want to catch it. This exception is raised in notmain module. The problem is I can't catch my exception raised in notmain module.

main.py:

class MyException(Exception):
    pass

m = __import__('notmain')
try:
    m.func()
except MyException as e:
    print(type(e))
    print('ops')

notmain.py:

def func():
    import main # 1
    # from main import MyException # 2
    # from main import MyException as MyException # 3

    raise main.MyException # 1
    # raise MyException # 2, 3

I tried different import methods, with the same result. When I run main.py, I see this:

<class 'main.MyException'>
ops
Traceback (most recent call last):
  File "D:\exception\main.py", line 6, in <module>
    m.func()
  File "D:\exception\notmain.py", line 6, in func
    raise main.MyException # 1
main.MyException

This means exception is somehow caught, but why I see traceback? And why exception class has "main.MyException" name?

Now if I modify main.py a little bit and run it:

try:
    raise MyException
except MyException as e:
    print(type(e))
    print('ops')

I'll see what's expected:

<class '__main__.MyException'>
ops

I don't know why this class MyException has different names in main.py and in notmain.py? And why Python can't catch it as expected?

Thank you :)

+6  A: 

Your module main is imported twice (as main and __main__), each having its own class MyException. You should consider redesigning your application to avoid circular imports.

Denis Otkidach
A: 

The __main__ name, with underscores, is an automatic namespace for the program being called. A workaround would be to declare the exception in a third file (or have a third file that is the user-called program, and just a single method in your "real" program).

Also, the way you import notmain may have something to do with it. Why not just "from notmain import func" ?

Rasmus Kaj
Thanks. I import modules dynamically (I know module's name only in runtime), so __import__ is the only way to do it.
race1