我有以下项目层次结构:
project_dir
lib
__init__.py
...
some_script.py
...
agent
__init__.py
...
errors.py
some_agent_script.py
...
lib / agent / erros.py中有SomeException类定义 我使用以下代码将它们导入lib / agent / some_agent_script.py:
from errors import SomeException
我还使用以下代码导入lib / some_script.py
from agent.errors import SomeException
问题是当我在lib / agent / some_agent_script.py中引发SomeException时,lib / some_script.py无法在except块中捕获它:
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)
我可以在sys.modules中看到erros模块被导入了两次:第一个是'agent.errors'键,第二个是'lib.agent.errors'键
以下代码是正确的,但它不是一个漂亮的解决方案:
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')
我该怎么做才能让这个模块不要导入两次?
答案 0 :(得分:2)
您应该始终使用完全限定的导入。
from lib.agent.errors import SomeException
在使用它的每个模块中执行此操作。然后它将始终具有相同的包名称。 您可能还应该更改顶级包名称。名称“lib”太通用了。
如果您碰巧将模块命名为基本模块或“库存”模块,这也可以省去一些麻烦。例如,假设您创建了一个模块lib/agent/socket.py
并在lib/agent/some_agent_script.py
中编写了import socket
。你实际上不会得到你的模块,而是股票。
所以最好养成一直使用完全合格的软件包名称的习惯,如果可以的话,除了共同的根目录。
另一种方法是使用绝对导入。
from __future__ import absolute_import
import .errors
注意前导点。这显式从当前包导入。它也应该解决你的问题,但我承认我没有尝试过。