python关于包的题怎么做_Python自定义包引入
python中的Module是比較重要的概念。常見的情況是,事先寫好一個.py文?件,在另一個文件中需要import時,將事先寫好的.py文件拷貝?到當(dāng)前目錄,或者是在中增加事先寫好的.py文件所在的目錄,然后import。這樣的做法,對于少數(shù)文件是可行的,但如果程序數(shù)目很?多,層級很復(fù)雜,就很吃力了。有沒有辦法,像Java的Package一樣,將多個.py文件組織起來,以便在外部統(tǒng)一調(diào)用,和在內(nèi)部互相調(diào)用呢?答案是有的。主要是用到python的包的概念,python
__init__.py在包里起一個比較重要的作用要弄明白這個問題,首先要知道,python在執(zhí)行import語句時,到底進行了什么操作,按照python的文檔,它執(zhí)行了如下操作:第1步,創(chuàng)建一個新的,空的module對象(它可能包含多個module);第2步,把這個module對象插入sys.module中第3步,裝載module的代碼(如果需要,首先必須編譯)第4步,執(zhí)行新的module中對應(yīng)的代碼。在執(zhí)行第3步時,首先要找到module程序所在的位置,其原理為:如?果需要導(dǎo)入的module的名字是m1,則解釋器必須找到m1.py,它首先在當(dāng)前目錄查找,然后是在環(huán)境變量PYTHONPATH中查找。?PYTHONPATH可以視為系統(tǒng)的PATH變量一類的東西,其中包含若干個目錄。如果PYTHONPATH沒有設(shè)定,或者找不到m1.py,則繼續(xù)搜索?與python的安裝設(shè)置相關(guān)的默認(rèn)路徑,在Unix下,通常是/usr/local/lib/python。事實上,搜索的順序是:當(dāng)前路徑?(以及從當(dāng)前目錄指定的sys.path),然后是PYTHONPATH,然后是python的安裝設(shè)置相關(guān)的默認(rèn)路徑。正因為存在這樣的順序,如果當(dāng)前?路徑或PYTHONPATH中存在與標(biāo)準(zhǔn)module同樣的module,則會覆蓋標(biāo)準(zhǔn)module。也就是說,如果當(dāng)前目錄下存在xml.py,那么執(zhí)?行import
xml時,導(dǎo)入的是當(dāng)前目錄下的module,而不是系統(tǒng)標(biāo)準(zhǔn)的xml。了解了這些,我們就可以先構(gòu)建一個package,以普通module的方式導(dǎo)入,就可以直接訪問此package中的各個module了。Python中的package定義很簡單,其層次結(jié)構(gòu)與程序所在目錄的層次結(jié)構(gòu)相同,這一點與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可以為空,只要它存在,就表明此目錄應(yīng)被作為一個package處理。當(dāng)然,__init__.py中也可以設(shè)置相應(yīng)的內(nèi)容,下文詳細(xì)介紹。好了,現(xiàn)在我們在module_11.py中定義一個函數(shù):def funA():?print "funcA in module_11"?return在頂層目錄(也就是package1所在的目錄,當(dāng)然也參考上面的介紹,將package1放在解釋器能夠搜索到的地方)運行python:
>>>from package1.subPack1.module_11 import funcA>>>funcA()
funcA in module_11這樣,我們就按照package的層次關(guān)系,正確調(diào)用了module_11中的函數(shù)。細(xì)心的用戶會發(fā)現(xiàn),有時在import語句中會出現(xiàn)通配符*,導(dǎo)入某個module中的所有元素,這是怎么實現(xiàn)的呢?答案就在__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也就是說,以*導(dǎo)入時,package內(nèi)的module是受__init__.py限制的。好了,最后來看看,如何在package內(nèi)部互相調(diào)用。如果希望調(diào)用同一個package中的module,則直接import即可。也就是說,在module_12.py中,可以直接使用import module_11如果不在同一個package中,例如我們希望在module_21.py中調(diào)用module_11.py中的FuncA,則應(yīng)該這樣:from module_11包名.module_11 import
funcA
包機制
# a.py
def?add_func(a,b):
return?a+b
#?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定義包的方式稍微有點古怪,假設(shè)我們有一個parent文件夾,該文件夾有一個child子文件夾.child中有一個module
a.py .?如何讓Python知道這個文件層次結(jié)構(gòu)?很簡單,每個目錄都放一個名為_init_.py?的文件.該文件內(nèi)容可以為空.這個層次結(jié)構(gòu)如下所示:
parent?--__init_.py
--child
--?__init_.py
--a.py
b.py那么Python如何找到我們定義的module?在標(biāo)準(zhǔn)包sys中,path屬性記錄了Python的包路徑.你可以將之打印出來:
import?sys
print(sys.path)通常我們可以將module的包路徑放到環(huán)境變量PYTHONPATH中,該環(huán)境變量會自動添加到sys.path屬性.另一種方便的方法是編程中直接指定我們的module路徑到sys.path?中:importsysimportos
sys.path.append(os.getcwd()+'\\parent\\child')print(sys.path)fromaimportadd_funcprint(sys.path)print("Import?add_func?from?module?a")print("Result?of?1?plus?2?is:?")print(add_func(1,2))知識點:
如何定義模塊和包
如何將模塊路徑添加到系統(tǒng)路徑,以便python找到它們
如何得到當(dāng)前路徑
Python 包的相對導(dǎo)入講解
兩個常見錯誤
1. ValueError: Attempted relative import in non-package?
錯誤重現(xiàn)
目錄樹
1
2
3
4
5
6
7
8
9case1/
├──cat
│├──__init__.py
│└──cat.py
├──dog
│├──__init__.py
│└──dog.py
└──main.py
代碼
1
2
3
# case1/cat/cat.py
from..importdog
執(zhí)行
python case1/cat/cat.py
錯誤原因
python 使用一個模塊的屬性?name?來決定他在包結(jié)構(gòu)中的位置,所以當(dāng)直接執(zhí)行 cat.py 時,name?= \’main\’,cat.py 被當(dāng)作頂層模塊來處理了,自然不可能導(dǎo)入上層的任何對象了。
2. ValueError: Attempted relative import beyond toplevel package
錯誤重現(xiàn)
目錄樹
1
2
3
4
5
6
7
8
9
10
11case2/
├──cat
│├──__init__.py
│├──cat.py
│└──cat.pyc
├──dog
│├──__init__.py
│└──dog.py
├──__init__.py
└──main.py
代碼
1
2
3
4
5
6
# case2/cat/cat.py
from..importdog
# case2/main.py
importcat.cat
執(zhí)行
python case2/main.py
錯誤原因:
這里的 case2 是一個包,但當(dāng)你直接執(zhí)行 main.py 的時候,就沒有把完整的 case2 當(dāng)作一個包來處理了,可想而知,下層的 cat.py 自然找不到上層包了。即想要相對導(dǎo)入成功,必須讓下層的被導(dǎo)入對象是上層包或上層包內(nèi)的對象。
正確執(zhí)行的例子
目錄樹
1
2
3
4
5
6
7
8
9
10
11
12case3/
├──alpaca.py
├──main.py
└──pets
├──__init__.py
├──cat
│├──__init__.py
│└──cat.py
└──dog
├──__init__.py
└──dog.py
代碼
1
2
3
4
5
6
7
# case3/pets/cat/cat.py
from..dogimportdog
from..importdog
# case3/main.py
frompets.catimportcat
執(zhí)行
python case3/main.py
請注意,這里的 cat.py 中是不能導(dǎo)入 alpaca 的,因為 pets 已經(jīng)是這個包樹的頂層了。
另外一篇:
python的相對路徑導(dǎo)入問題
用python做項目,如果項目大了,或者想更好的管理程序,總是要使用包。包解決了命名沖突的問題。
今天在使用python的相對路徑導(dǎo)入的時候,遇到了不少的問題。
包導(dǎo)入情形:
1
2
3
4
5
6
7
8
9
10
11
src/
__init__.py
main.py
components/
__init__.py
expander.py
language_id.py
utilities/
__init__.py
functions.py
如果要在expander.py中引用functions.py中的內(nèi)容,或許這樣表示
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
使用相對路徑進行導(dǎo)入的文件,不能再當(dāng)作主文件執(zhí)行。原因如下:
http://blog.csdn.net/chinaren0001/article/details/7338041
3.錯誤三:no module named ***
在指定路徑下沒有找到該模塊。
另外:在main.py執(zhí)行的時候,沒有指定路徑的文件默認(rèn)與main.py是同一路徑。
總結(jié)
以上是生活随笔為你收集整理的python关于包的题怎么做_Python自定义包引入的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【HDU - 2612】Find a w
- 下一篇: 在线python视频教程_【好程序员】2