2013-04-03 125 views
0

说我有这样的目录结构:Python打包 - 这__init__.py的

mydir 
    __init__.py 
    innerdir 
     __init__.py 
     mymodule.py 

mymodule.py的内容很简单:

def hi(): 
    print 'hello, welcome' 

同时兼具__init__.py S的是

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

同样,如果我搬入mydir目录,提示那里,并尝试import innerdirinnerdir.mymodule

我可以成功地import mydir.innerdir,但我只能用它作为mydir.innerdir,而不仅仅是innerdir

+1

你应该可以'从mydir import innerdir'现在你不必使用整个路径 – dm03514 2013-04-03 23:25:21

+0

你看了[Packages](http://docs.python.org/2/tutorial/modules.html #packages)在教程中?它解释了我想你所问的几乎所有问题。 – abarnert 2013-04-03 23:28:53

+0

@abarnert我真的读过它,但我并不理解整个概念,我只是迷失了 – whatyouhide 2013-04-03 23:35:29

回答

3

你描述的一些东西,我甚至不知道你期望它做什么。但是从最后一段来看,这听起来像你很接近,所以我们从那里开始。

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

那怎么import作品在Python中,即使你忽略的包,只是有一堆东西持平,甚至只是标准库。例如,如果您import os,则可以执行os.listdir('.'),但不能仅仅执行listdir('.')

这里的解决方案是一样的,因为它是有:

from mydir import innerdir 

这其实不是非常有用,因为innerdir是什么也没有包在里面直接定义。你可能真的想要做的是from mydir.innerdir import mymodule。但这是如何去做你所问的。


如果你想知道为什么后面mydir.innerdirimport mydir不工作,我可以解释一下。

从教程的Packages部分:

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

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

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


如果你问,当你从内mydir运行(或将其添加到您的PYTHONPATH)会发生什么......嗯,在这种情况下,mydir不是包的话,那只是一个完整的目录的模块和包装(在这种情况下,只有一个包装,innerdir)。这很像做from mydir import innerdir

+0

好吧,这很公平。所以这导致了什么是最初的问题:请参阅我的文章的编辑。 – whatyouhide 2013-04-03 23:27:15

+0

@whatyouhide:究竟是什么原始问题?你提到了很多不同的东西。你问为什么'import mydir; mydir.innerdir'是一个'AttributeError'? – abarnert 2013-04-03 23:27:43

+0

已编辑,问题已解决 – whatyouhide 2013-04-03 23:34:57

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__'] 

(请注意,没有mymodulemydir.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,它解释了所有这些,并且具有与你在这里显示的完全一样的目录结构。

+0

非常有趣。你提到的最后一个选项实际上是我所期望的。为了好奇,是不是您提到的一些内置Python包使用的最后一个选项?例如,当你导入os时,你可以使用'os.path.isdir',这让我认为'path'是一个模块。这意味着'os'既是模块('os.exit()')**也是**包? – whatyouhide 2013-04-04 08:34:27

+0

包通常不会急于加载子包和子模块。然而,许多包在它们的'__init__'中有代码需要一些模块,所以这些模块将作为导入的副作用在包名称空间中。 – 2013-04-04 08:45:04

+0

顺便说一句,这没有完成的原因是使用一个包的任何一个部分不需要解析和加载到每个单个子包和子模块中的每个单一定义的内存中。对于大型软件包来说,这会在内存使用和启动时间方面产生巨大的差异!避免急于加载'__init__',除非你有一个非常有说服力的理由! – 2013-04-04 08:48:13