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.
from lib.agent.errors import SomeException
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.py
and in lib/agent/some_agent_script.py
you wrote import 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.
from __future__ import absolute_import
import .errors
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With