I have following project hierarchy:
project_dir
lib
__init__.py
...
some_script.py
...
agent
__init__.py
...
errors.py
some_agent_script.py
...
There is the SomeException class definition in lib/agent/erros.py
I use following code to import them inside lib/agent/some_agent_script.py:
from errors import SomeException
Also I use following code to import in lib/some_script.py
from agent.errors import SomeException
The problem is when I raise a SomeException in lib/agent/some_agent_script.py then lib/some_script.py can not catch it in an except block:
try:
# Here comes a call to lib/agent/some_agent_script.py function
# that raises SomeException
except SomeException, exc:
# Never goes here
print(exc)
except Exception, exc:
print(exc.__class__.__name__) # prints "SomeException"
# Let's print id's
print(id(exc.__class__))
print(id(SomeException))
# They are different!
# Let's print modules list
pprint.pprint(sys.modules)
I can see in sys.modules that erros module was imported twice: the first is with ‘agent.errors’ key and the second is with ‘lib.agent.errors’ key
The following code goes right, but it’s not a beautiful solution:
agent_errors = sys.modules.get('agent.errors')
from agent_errors import SomeException
try:
# Here comes a call to lib/agent/some_agent_script.py function
except SomeException:
print('OK')
What should I do to make this module not to import twice?
You should always use fully qualified imports.
Do this in every module that uses it. Then it will always have the same package name.
You should probably also change the top-level package name. The name “lib” is too generic.
This will also save you some headaches if you happen to name a module the same as a base, or “stock”, module. For example, suppose you created a module
lib/agent/socket.pyand inlib/agent/some_agent_script.pyyou wroteimport socket. You would not actually get your module, but the stock one.So it’s better to get in the habit of always using fully qualified package names, off a common root if you can.
An alternative is to use absolute imports.
Note the leading dot. This explicitly imports from the current package. It should also fix your problem, but I admit I haven’t tried it.