防止包本身导入

时间:2012-07-16 23:05:18

标签: python namespaces

好的,我们举个例子(下面的原始问题)。

我制作了一个名为“myproject”的软件包,它显示了我面临的问题。

  1. 在此处下载资料包:https://dl.dropbox.com/u/11013311/myproject.zip
  2. 安装包(例如:sudo python setup.py develop)
  3. 打开Ipython会话并输入:“import myproject”
  4. 如果您开始输入“myproject”。并按两次选项卡以获取可用的方法/值...,您将看到“myproject.myproject”,它本身也显示相同的问题。
  5. 你们其中一个人能够解释我的错误吗? Andrew Alcock 的回答并没有帮助我解决它,或者至少我没有看到问题出在哪里。

    当然,通过这样一个简单的示例,包__init__.py文件不需要那么复杂,但在我的真实项目中,我需要通过{{COOL实例访问myproject.COOL实例。 1}}。

    感谢您的回答!

    编辑:我已经授予 utapyngo 赏金,因为他的解决方案很有效,而且我学到了更多东西(相对于深子模块的导入)。但是我要感谢 Andrew nehz 的答案( nehz 也提供了一个解决方案来解决我的问题,但我非常主观地找到了它“不那么漂亮”; Andrew 提供了有用的建议。太糟糕了,我无法分享赏金。

    **

    原始问题:

    **

    我不确定我是否正确地表达了这个问题。我创建了一个包含许多子包的大型代码,为简单起见,我们将其称为“CODE”。

    问题是:'CODE'出现在名称空间中,所以我可以CODE.CODECODE.CODE.CODE等...无数次,这对我来说很奇怪,可能是(我猜) )暗示某些事情是错误的(尽管代码在没有警告的情况下完美运行)。

    我想这个问题与我的__init__.py和我的代码结构有关,所以我在这里给出了更多的信息。

    简化的代码结构:

    CODE
      | __init__.py
      | tools
         | __init__.py
         | mytools.py
      | other
         | __init__.py
         | init.py
      | sub
         | __init__.py
         | module.py
    

    文件:__init__.py(第一个,CODE的根}

    import CODE.tools.mytools as MyTools
    import CODE.other.init
    
    OBJ = CODE.other.init.function()
    ...
    

    文件mytools.py不会从CODE或任何其他可能导入OBJ的模块导入OBJinit.py可以导入mytools.py等模块。 最后,像module.py这样的模块可以导入mytools.pyOBJ(来自CODE)。通常,所有导入都是使用绝对导入进行的,例如:from CODE.sub.module import func

    有没有人对这种行为有解释?我没有在SO上找到任何相关问题,但可能是由于我的错误措辞。

3 个答案:

答案 0 :(得分:3)

问题是您导入的(基本上是顶级__init__.py文件)包含对其自身(模块)的引用进口。由于模块现在具有自己的命名空间,因此您现在可以将其作为CODE.CODE访问。 ...... .CODE.MyTools。

我建议:

1)在每个子包(工具,其他)中都有__init__.py

2)在CODE的模块中,不要“导入CODE”或任何子包。而是直接导入您感兴趣的模块(文件)。

例如,在CODE.sub.module.py中:

不要:

import CODE.other     # "other" is a package (a directory)

执行:

import CODE.other.init    # "init" is a module (a file)

这就是理智所在。

编辑:重新定义您的具体示例

  

文件mytools.py不从CODE或任何其他可能导入OBJ的模块导入OBJ。 init.py可以导入mytools.py等模块。

  

最后,像module.py这样的模块可以导入mytools.py或OBJ(来自CODE)。

这是你的问题。不要在这里导入CODE。如果你需要简化相当长的“CODE.other.init.function”,可以使用from ... import语句来实现:

> from CODE.other.init import function as OBJ 

但要注意许多Pythonite不喜欢这种情况,因为它会导致混淆。

  

通常,所有导入都是使用绝对导入进行的,例如:来自CODE.sub.module import func。

答案 1 :(得分:1)

使用绝对导入后删除引用:

import atexit

import myproject.mymodule_one.suby as SubY
obj = SubY.myclass()
import myproject.mymodule_two.initialization

COOL = myproject.mymodule_two.initialization.create_cool()
del myproject

编辑: FYI删除引用将不会卸载模块,并且COOL中的实例仍然有效。

答案 2 :(得分:1)

在您的主__init__.py中,您不必甚至不应该引用您的模块名称(谁知道,您可能希望将来重命名它)。

只需替换

import myproject.mymodule_...

import mymodule_...

现在没有myproject.myproject

>>> dir(myproject)
['COOL', 'SubY', '__builtins__', '__doc__', '__file__', '__name__', '__package__',
 '__path__', '__version__', 'atexit', 'exit_report', 'mymodule_one', 'mymodule_two',
 'obj', 'toto']