您的位置:首页 > 编程语言 > Python开发

python module package import

2015-07-11 17:52 686 查看
今天主要研究了一下python的import。

首先要明确两个概念,模块和包

模块一般指一个python文件,类似于.c文件。其中包含了很多def的函数和一些变量。包一般指一个目录,下面有一些模块。

我做了一些实验,

如果没有包的情况下,假如我有一个模块在./pythonmod/文件夹下。那么在.文件夹下的一个py文件中执行

from pythonmod import a

a.say()

会报错,原因就是pythonmod既不是一个module也不是一个包,无法从中import。

我们只能这样操作

import sys

sys.path.append("./pythonmod/")

import a

a.say()

原理就是把pythonmod这个目录放到python的查找路径中去。这样我import a的时候python就会找到pythonmod下的a,并把它作为模块import。

要想不这么麻烦,我们需要把pythonmod变成一个包,要变包,pythonmod目录下就必须要有__init__.py文件。

1.__init__.py文件为空

以下几种操作都是可以的

import pythonmod.a
pythonmod.a.say()

import pythonmod.a as a
a.say()

from pythonmod import a
a.say()

from pythonmod.a import say
say()

from pythonmod.a import *
say()


注意到调用时要从import之后的包/模块/函数名写起,除非使用了as,as相当于取了个别名。

这时以下操作不允许

from pythonmod import *
say()


原因就是__init__.py中并没有定义pythonmod中有哪些module。之前我们都是显示的指明从pythonmod中import一个模块a,所有可以,现在不指明,python就不知道要import谁了。

2.__init__.py中包含了__all__信息

只要我们在__init__.py中加入

__all__=["a","b"]


其中a和b是我们pythonmod包中的模块。我们就可以执行

from pythonmod import *


的操作了。

注意:import的东西只能为一个module或module中的函数,变量,类而不能为一个package,例如我的目录结构为

pythonmod

apkg

a.py

__init__.py

bpkg

b.py

__init__.py

c.py

__init__.py

test.py

的时候,在test.py中执行

import pythonmod.apkg
pythonmod.apkg.a.say()




from pythonmod import apkg
apkg.a.say()


都是不行的。

报错是apkg中没有attribute a。这是因为虽然import能对一个package进行操作,但是我们说过了import的东西都被认为是一个module或者某个module的成员函数/类/变量。pythonmod.apkg.a.say()在执行的时候,pythonmod.apkg被理解成一个module,然后找这个module的a这个成员的时候发现没有,因此报错了。所以我们说import可以把一个package当成module去import,而且不会报错,但这并没有什么用,因为我们无法调用它。只有当我们import一个module,然后执行module.func()进行函数调用;或者直接import一个函数,然后直接调用的时候,这个import才是有意义的。

这里我们应该这样写

import pythonmod.apkg.a
pythonmod.apkg.a.say()


或者

from pythonmod.apkg import a
a.say()


大家可能有个问题,明明很多时候我的确只import了一个package,但是为什么我能使用package.module.func这样的方法调用func呢。

原因就在于,写这个package的人在package的__init__.py中帮你import了这个module。

例如还是上面的例子。

我在pythonmod下面的__init__.py中添加import apkg

在apkg的__init__.py中添加import a。

然后在test.py中,我们写

import pythonmod
pythonmod.apkg.a.say()
pythonmod.bpkg.b.say()


会发现import之后的第一句执行成功了,而第二句失败了,原因就是pythonmod的__init__.py中我们没有import bpkg,但import apkg了。

如果写包的人在__init__.py中帮我们把import包的子包或包的模块写好了,那我们就只要import一个包就可以了。

举个例子,numpy是一个package,但是我们只要import一个numpy就可以执行诸如np.zeros()这样的操作。这是因为在numpy的实现中,(numpy的路径在/usr/lib/python2.7/dist-packages/numpy),在setup.py里,已经将包括numarray的多个子包全部import,具体怎么实现的我也还没有看出来,但是可以知道的是numpy的package一定是已经把所有函数都变得直接用类似于np.zeros()这个方式调用,而不需要用np.numarray.functions.zeros()这种方式。

现在如果我想在a.py中import bpkg.b这个module呢?

如果我们直接在a.py中这样写

import bpkg.b

bpkg.b.say()

报错是没有叫bpkg.b的module。

那么好,之前我们说了可以直接import一个package,即便这并没有任何用处,但并不会报错,那么假如我们在a.py中这样写呢

import bpkg

还是报错,说没有bpkg这个module

那假如这样写呢

import pythonmod.bpkg

还是报错,说没有pythonmod.bpkg这个module。

这是为什么呢?原因就在于我们的module的搜索路径变了。

原来我执行test.py的时候,默认搜索路径包括sys.path中指定的路径(其中包括当前路径)还有一些PYTHONPATH这样的其他路径。那时当前路径下有pythonmod这个目录,自然也就找到了。而在apkg这个文件夹中,自然找不到bpkg或者pythonmod这两个目录了。

为了解决这个问题,我们可以在sys.path中增加一个bpkg的路径就可以了。

import sys
sys.path.append('..')
import bpkg.b
bpkg.b.say()


或者我直接在test.py的同级目录下执行python -m pythonmod.apkg.a,并在a.py中写

import pythonmod.bpkg.b
pythonmod.bpkg.b.say()


也能成功
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: