python中的自訂module

來源:互聯網
上載者:User

python中的Module是比較重要的概念。常見的情況是,事先寫好一個.py文 件,在另一個檔案中需要import時,將事先寫好的.py檔案拷貝 到目前的目錄,或者是在sys.path中增加事先寫好的.py檔案所在的目錄,然後import。這樣的做法,對於少數檔案是可行的,但如果程式數目很 多,層級很複雜,就很吃力了。
有沒有辦法,像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

# 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))

知識點:

     

如何定義模組和包

     

如何將模組路徑添加到系統路徑,以便python找到它們

     

如何得到當前路徑

原文地址:http://blog.sina.com.cn/s/blog_615c388d01017b5o.html

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.