Python包装 - __init__.py

时间:2013-04-03 23:17:31

标签: python python-module

假设我有这样的目录结构:

mydir
    __init__.py
    innerdir
        __init__.py
        mymodule.py

mymodule.py的内容很简单:

def hi():
    print 'hello, welcome'

虽然__init__.py都是为空

现在,如果我在mydir目录之外,并打开Python提示并尝试import mydir然后使用mydir.innerdir,则会收到错误(NameError: 'innerdir' is not defined )。

如果我进入mydir目录,提示相同并尝试import innerdirinnerdir.mymodule

我可以成功import mydir.innerdir,但之后我只能将其用作mydir.innerdir,而不只是innerdir

2 个答案:

答案 0 :(得分:3)

你描述的一些东西,我甚至不确定你的预期。但是从你的最后一段来看,听起来你很近,所以让我们从那里开始吧。

  

我可以成功导入mydir.innerdir,但是我只能将其用作mydir.innerdir,而不仅仅是innerdir。为什么我必须指定整个路径?

这就是import在Python中的工作方式,即使你忽略了包,只是有一堆扁平的东西,甚至只是标准的库。例如,如果您import os,则可以执行os.listdir('.'),但不能只执行listdir('.')

这里的解决方案和它在那里一样:

from mydir import innerdir

这实际上并不是非常有用,因为innerdir是一个没有直接定义的包。您可能真正想要做的是from mydir.innerdir import mymodule。但这就是你怎么做的。


如果您想知道为什么import mydir后跟mydir.innerdir不起作用,我可以解释一下。

从教程的Packages部分:

  

...当使用import item.subitem.subsubitem之类的语法时,除了最后一项之外的每个项目都必须是一个包;最后一项可以是模块或包,但不能是前一项中定义的类或函数或变量。

所以,你所做的不应该做任何有用的事情。但它实际上做了什么?

它导入包就像它是一个模块一样。这意味着您在包本身中定义的任何内容 - 函数,类,甚至模块 - 都将作为mydir的成员提供。但这并不会自动导入包目录中的任何子包或子模块 - 请记住,您将作为模块导入,而不是作为包


如果您询问从mydir内部运行时会发生什么(或将其添加到您的PYTHONPATH)...那么,在这种情况下,mydir根本不是包,它是只是一个充满模块和包的目录(在这种情况下,只是一个包,innerdir)。这非常像做from mydir import innerdir

答案 1 :(得分:1)

直接导入的包不会自动将子包或子模块放入其命名空间:

>>> import mydir
>>> dir(mydir)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

(请注意,此处没有innerdir。)

但是如果你通过包导入,Python会将命名空间连接在一起:

>>> import mydir.innerdir
>>> dir(mydir)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', 'innerdir']
>>> dir(mydir.innerdir)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__']

(请注意mymodule中没有mydir.innerdir。)

Python允许您使用__all__中的__init__.py魔术变量明确说明要在包中自动包含哪些子模块,但默认情况下它只会运行__init__.py中的代码代码而不做任何其他事情。

您可以执行以下任何操作:

import mydir.innerdir.mymodule; mydir.innerdir.mymodule.hi()
from mydir.innerdir import mymodule; mymodule.hi()
from mydir.innerdir.mymodule import hi; hi()

或者,您可以编辑__init__.py个文件以包含__all__变量以进行通配符导入。

# file mydir/innerdir/__init__.py
print 'Running mydir/innerdir/__init__.py'
__all__ = ['mymodule']

然后你可以做这样的事情:

from mydir.innerdir import *; mymodule.hi()

更疯狂,你可以急切地导入子包和模块(我不推荐这个!):

# file mydir/__init__.py
print 'Running mydir/__init__.py'
import innerdir

# file mydir/innerdir/__init__.py
print 'Running mydir/innerdir/__init__.py'
import mymodule

现在这些将起作用:

import mydir; mydir.innerdir.mymodule.hi()
from mydir import innerdir; innerdir.mymodule.hi()

您可能想要了解documentation for packages,它解释了所有这些并且具有与您在此处显示的目录结构完全相同的目录结构。