Python自定义包引入【新手必学】

 

前言
本文的文字及图片来源于网络,仅供学习、交流使用,不具备任何商业用途,版权归原做者全部,若有问题请及时联系咱们以做处理。
做者:sys_songhtml


python中的Module是比较重要的概念。常见的状况是,事先写好一个.py文 件,在另外一个文件中须要import时,将事先写好的.py文件拷贝 到当前目录,或者是在sys.path中增长事先写好的.py文件所在的目录,而后import。这样的作法,对于少数文件是可行的,但若是程序数目很 多,层级很复杂,就很吃力了。若是你刚学python不久,有问题找不到人解答的话。能够去小编的Python交流.裙 :一久武其而而流一思(数字的谐音)转换下能够找到了,里面有最新Python教程项目可拿,不懂的问题多跟里面的人交流,都会解决哦!python

有没有办法,像Java的Package同样,将多个.py文件组织起来,以便在外部统一调用,和在内部互相调用呢?答案是有的。
主要是用到python的包的概念,python __init__.py在包里起一个比较重要的做用
要弄明白这个问题,首先要知道,python在执行import语句时,到底进行了什么操做,按照python的文档,它执行了以下操做:
1步,建立一个新的,空的module对象(它可能包含多个module);
2步,把这个module对象插入sys.module中
3步,装载module的代码(若是须要,首先必须编译)
4步,执行新的module中对应的代码。

在执行第3步时,首先要找到module程序所在的位置,其原理为:
如 果须要导入的module的名字是m1,则解释器必须找到m1.py,它首先在当前目录查找,而后是在环境变量PYTHONPATH中查找。 PYTHONPATH能够视为系统的PATH变量一类的东西,其中包含若干个目录。若是PYTHONPATH没有设定,或者找不到m1.py,则继续搜索 与python的安装设置相关的默认路径,在Unix下,一般是/usr/local/lib/python。
事实上,搜索的顺序是:当前路径 (以及从当前目录指定的sys.path),而后是PYTHONPATH,而后是python的安装设置相关的默认路径。正由于存在这样的顺序,若是当前 路径或PYTHONPATH中存在与标准module一样的module,则会覆盖标准module。也就是说,若是当前目录下存在xml.py,那么执 行import xml时,导入的是当前目录下的module,而不是系统标准的xml。

了解了这些,咱们就能够先构建一个package,以普通module的方式导入,就能够直接访问此package中的各个module了。

Python中的package定义很简单,其层次结构与程序所在目录的层次结构相同,这一点与Java相似,惟一不一样的地方在于,python中的package必须包含一个__init__.py的文件。
例如,咱们能够这样组织一个package:


package1/
    __init__.py
    subPack1/
        __init__.py
        module_11.py
        module_12.py
        module_13.py
    subPack2/
        __init__.py
        module_21.py
        module_22.py
    ……

__init__.py能够为空,只要它存在,就代表此目录应被做为一个package处理。固然,__init__.py中也能够设置相应的内容,下文详细介绍。

好了,如今咱们在module_11.py中定义一个函数:

def funA():
    print "funcA in module_11"
    return

在顶层目录(也就是package1所在的目录,固然也参考上面的介绍,将package1放在解释器可以搜索到的地方)运行python:

>>>from package1.subPack1.module_11 import funcA
>>>funcA()
funcA in module_11

这样,咱们就按照package的层次关系,正确调用了module_11中的函数。

细心的用户会发现,有时在import语句中会出现通配符*,导入某个module中的全部元素,这是怎么实现的呢?
答案就在__init__.py中。咱们在subPack1的__init__.py文件中写

__all__ = ['module_13', 'module_12']

而后进入python
>>>from package1.subPack1 import *
>>>module_11.funcA()
Traceback (most recent call last):
  File "", line 1, in 
ImportError: No module named module_11

也就是说,以*导入时,package内的module是受__init__.py限制的。

好了,最后来看看,如何在package内部互相调用。
若是但愿调用同一个package中的module,则直接import便可。也就是说,在module_12.py中,能够直接使用
import module_11

若是不在同一个package中,例如咱们但愿在module_21.py中调用module_11.py中的FuncA,则应该这样:
from module_11包名.module_11 import funcA
编程

 

包机制网络

# a.py
def add_func(a,b):
    return a+b
app

# b.py
from a import add_func # Also can be : import a

print ("Import add_func from module a")
print ("Result of 1 plus 2 is: ")
print (add_func(1,2))    # If using "import a" , then here should be "a.add_func"

module能够定义在包里面.Python定义包的方式稍微有点古怪,假设咱们有一个parent文件夹,该文件夹有一个child子文件夹.child中有一个module a.py . 如何让Python知道这个文件层次结构?很简单,每一个目录都放一个名为_init_.py 的文件.该文件内容能够为空.这个层次结构以下所示:
函数

parent 
  --__init_.py
  --child
    -- __init_.py
    --a.py

b.py
那么Python如何找到咱们定义的module?在标准包sys中,path属性记录了Python的包路径.你能够将之打印出来:
import sys

print(sys.path)
一般咱们能够将module的包路径放到环境变量PYTHONPATH中,该环境变量会自动添加到sys.path属性.另外一种方便的方法是编程中直接指定咱们的module路径到sys.path 中:
import sys
import os
sys.path.append(os.getcwd()+'\\parent\\child')
print(sys.path)
from a import add_func
print (sys.path)
print ("Import add_func from module a")
print ("Result of 1 plus 2 is: ")
print (add_func(1,2))

知识点:
post

      如何定义模块和包学习

      如何将模块路径添加到系统路径,以便python找到它们spa

      如何获得当前路径.net

 

http://www.dai3.com/python-import.html下文地址:

 

Python 包的相对导入讲解

 

两个常见错误

1. ValueError: Attempted relative import in non-package​

错误重现
目录树

 

 

代码

 

 

执行

python case1/cat/cat.py

错误缘由

python 使用一个模块的属性 name 来决定他在包结构中的位置,因此当直接执行 cat.py 时,name = \’main\’,cat.py 被看成顶层模块来处理了,天然不可能导入上层的任何对象了。

2. ValueError: Attempted relative import beyond toplevel package

错误重现

目录树

 

 

代码

 

 

执行

python case2/main.py

错误缘由:

这里的 case2 是一个包,但当你直接执行 main.py 的时候,就没有把完整的 case2 看成一个包来处理了,可想而知,下层的 cat.py 天然找不到上层包了。即想要相对导入成功,必须让下层的被导入对象是上层包或上层包内的对象。

正确执行的例子

目录树

 

 

代码

 

 

执行

python case3/main.py

请注意,这里的 cat.py 中是不能导入 alpaca 的,由于 pets 已是这个包树的顶层了。

From:http://hiaero.net/python-relative-imports/


另一篇:

python的相对路径导入问题

用python作项目,若是项目大了,或者想更好的管理程序,老是要使用包。包解决了命名冲突的问题。
今天在使用python的相对路径导入的时候,遇到了很多的问题。
包导入情形:

 

 

若是要在expander.py中引用functions.py中的内容,或许这样表示
from ..utilities import functions.py

1.错误一:ValueError:Attemptedrelative import beyond toplevel package
这个问题是由于到达了包的最顶层,而最顶层不是一个包。
解决方法:在main.py同级添加一个目录mod,包含components和utilities,并在mod中添加一个init.py,便可解决
参见:http://stackoverflow.com/questions/4175534/relative-imports-in-python

2.错误二:ValueError: Attempted relative import in non-package
使用相对路径进行导入的文件,不能再看成主文件执行。缘由以下:

http://blog.csdn.net/chinaren0001/article/details/7338041

3.错误三:no module named ***
在指定路径下没有找到该模块。

另外:在main.py执行的时候,没有指定路径的文件默认与main.py是同一路径。本期分享到此,若是你刚学python不久,没有最新学习路线或有问题找不到人解答的话。能够去小编的Python交流.裙 :一久武其而而流一思(数字的谐音)转换下能够找到了,里面有最新Python教程项目可拿,不懂的问题多跟里面的人交流,都会解决哦!

相关文章
相关标签/搜索