python的模組

來源:互聯網
上載者:User

標籤:python 模組

參考:

https://www.cnblogs.com/bobo0609/p/6938012.html

https://docs.python.org/2/tutorial/modules.html


1.簡介

在Python中,一個.py或者.pyc檔案就稱之為一個模組(Module)。即一個檔案被看作一個獨立的模組,一個模組也可以被看做是一個檔案

.py:存放的是python源碼

.pyc:存放的是python解譯器對源碼編譯後的位元組碼


python把檔案名稱去掉.py/.pyc尾碼作為模組名,比如 os.py ,那麼它的模組名就是 os


那麼假設我們當前路徑有個os.py,python怎麼知道它的位置,並匯入使用呢?

這裡就涉及到python的模組搜尋路徑,它的搜尋次序如下:

<1>當前路徑

<2>PYTHONPATH變數自訂的路徑(PYTHONPATH是系統自訂的環境變數,類似centos中的PATH)

<3>安裝python時所定義的路徑


有人會疑惑,python怎麼知道我當前的路徑在哪?


這是因為,python的程式包括一個頂層程式檔案和其它的模組檔案,這個頂層檔案相當於程式執行的入口,類似shell指令碼,我們執行指令碼時必須寫明絕對路勁或者切到對應路徑去執行(這個時候路徑就傳遞了),python也是同理


例子:


        [[email protected] python_learn]# pwd/root/python_learn[[email protected] python_learn]# cat getvalue.py#!/usr/local/anaconda2/bin/pythonx='Gx'y='Gy'z='Gz'def f1(x,y,z):    x='Ex'    z='Ez'    print x,y,z    def f2(x,y,z):x='Lx'print x,y,z    f2(x,y,z)f1(x,y,z)[[email protected] python_learn]# cat index.py import getvalueprint x[[email protected] python_learn]# python  index.py Ex Gy EzLx Gy EzTraceback (most recent call last):  File "index.py", line 2, in <module>    print xNameError: name 'x' is not defined



這裡index.py作為程式入口匯入了getvalue這個模組,顯然,這裡python找到了getvalue模組,因為程式執行到了print x,但是為什麼會有"Ex Gy Ez"這些輸出呢?


這是因為:python在首次匯入模組(import 或者reload)的時候,會立即執行模組檔案的頂層程式碼(不在函數內的代碼,比如變數x'=Gx',函數定義def f1等,只要頂格寫都會被執行),而位於函數主體內的代碼直到函數被調用後才會執行,所以f1(x,y,z)函數被調用了,列印出了"Ex Gy Ez",而f1又自己調用了f2,所以f2函數列印了"Lx Gy Ez"


那麼,既然模組有匯入成功,x變數應該有定義,為何又提示“name 'x' is not defined”呢?


這是因為:為了避免大家的相同編程習慣導致各種變數覆蓋(比如張三和李四被指派寫兩個不同的模組,張三習慣在他的變數中使用x,李四也習慣這樣,那麼當兩個模組都被匯入時,因為變數名相同,必然有一個的值會被覆蓋掉),於是python在匯入模組時,以模組名建立一個新的名稱空間,在新的名稱空間中建立變數。 簡單地說,當匯入getvalue模組的x變數的時候,此時x不再被當成x,而是被當成getvalue.x


例子:(接上例)

    [[email protected] python_learn]# cat index.py import getvalueprint getvalue.x[[email protected] python_learn]# python index.py Ex Gy EzLx Gy EzGx


可以看見,此時的print 語句已經可以正常輸出。


那麼,如果我想隨時隨地可以匯入getvalue模組,而又不想切到指定路徑去,那麼該怎麼辦呢?

這個時候,就要用到sys.path這個變數了


例子:


        In [2]: import sysIn [3]: sys.pathOut[3]: ['', '/usr/local/anaconda2/bin', '/usr/local/anaconda2/lib/python27.zip', '/usr/local/anaconda2/lib/python2.7', '/usr/local/anaconda2/lib/python2.7/plat-linux2', '/usr/local/anaconda2/lib/python2.7/lib-tk', '/usr/local/anaconda2/lib/python2.7/lib-old', '/usr/local/anaconda2/lib/python2.7/lib-dynload', '/usr/local/anaconda2/lib/python2.7/site-packages', '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions', '/root/.ipython']In [4]: sys.path.insert('/root/python_learn/')---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-4-b628fd39dcd4> in <module>()----> 1 sys.path.insert('/root/python_learn/')TypeError: insert() takes exactly 2 arguments (1 given)In [5]: help (list.insert)In [6]: sys.path.insert(,'/root/python_learn/')  File "<ipython-input-6-c98c91c9451b>", line 1    sys.path.insert(,'/root/python_learn/')                    ^SyntaxError: invalid syntaxIn [7]: sys.path.insert(0,'/root/python_learn/')In [8]: sys.pathOut[8]: ['/root/python_learn/', '', '/usr/local/anaconda2/bin', '/usr/local/anaconda2/lib/python27.zip', '/usr/local/anaconda2/lib/python2.7', '/usr/local/anaconda2/lib/python2.7/plat-linux2', '/usr/local/anaconda2/lib/python2.7/lib-tk', '/usr/local/anaconda2/lib/python2.7/lib-old', '/usr/local/anaconda2/lib/python2.7/lib-dynload', '/usr/local/anaconda2/lib/python2.7/site-packages', '/usr/local/anaconda2/lib/python2.7/site-packages/IPython/extensions', '/root/.ipython']In [9]: import  getvalueEx Gy EzLx Gy EzIn [10]: getvalue.xOut[10]: 'Gx'


python按照sys.path的順序來尋找模組,需要注意的是,insert方法需要兩個參數,第一個是索引,這裡使用0,放在第一位,優先尋找我們自己的目錄


如果我們再次import,python並不會再次執行頂層程式碼,而是簡單地重載下記憶體中的對象


例子:

        In [29]: import getvalueIn [30]: getvalue reload  File "<ipython-input-30-7cba10969034>", line 1    getvalue reload                  ^SyntaxError: invalid syntaxIn [31]: help(reload)In [32]: reload(getvalue)Ex Gy EzLx Gy EzOut[32]: <module 'getvalue' from '/root/python_learn/getvalue.pyc'>



現在,模組載入沒什麼問題了,但是我覺得每次都要敲完整模組名getvalue,太煩人了,有沒有什麼辦法呢?

這個時候就要用到import-as語句了


例子:


        In [33]: import getvalue as gIn [34]: g.xOut[34]: 'Gx'



import xx  as x:把本來先建立名稱空間名為getvlaue改成了g,所以調用就簡單了,因為是修改所以此時getvalue這個名稱空間是不存在的,所以不能用getvalue+'.'擷取值


那麼如果我比較任性,就想覆蓋當前環境中的變數x呢?

這個時候就得用到from-import 語句了


例子:

        In [35]: from getvalue import xIn [36]: xOut[36]: 'Gx'



from-import語句只會載入對應的屬性或者方法到當前的名稱空間,所以其他語句不會執行


所以python匯入模組,大概分成以下幾類:

import:直接匯入

import Module as Module_alias:給變數取別名

from Module import Attribute/Method: 匯入部分屬性/方法

reload(Module):重新匯入


既然作為模組,就該有作為模組的覺悟,一匯入就瞎執行是會被clear的-_-!!

所以我們不該讓模組中包含不該執行的語句,比如函數不該被調用。但是我又想這個模組檔案有時作為程式頂層檔案執行,有時作為模組被匯入,那麼有辦法嗎?


這個時候就可以用到內建屬性__name__了


例子:


        [[email protected] python_learn]# cp getvalue.py  New.py[[email protected] python_learn]# vi New.py [[email protected] python_learn]# cat New.py #!/usr/local/anaconda2/bin/pythonx='Gx'y='Gy'z='Gz'def f1(x,y,z):    x='Ex'    z='Ez'    print x,y,z    def f2(x,y,z):x='Lx'print x,y,z    f2(x,y,z)if __name__ == "__main__" :    f1(x,y,z)[[email protected] python_learn]# python New.py Ex Gy EzLx Gy Ez============================================In [6]: import NewIn [7]: New.xOut[7]: 'Gx'In [8]: reload(New)Out[8]: <module 'New' from 'New.pyc'>In [9]: New.__name__Out[9]: 'New'


這裡的內建變數__name__,如果程式是頂層檔案則為"__main__",否則為模組名


2.import的工作機制(摘抄自:https://www.cnblogs.com/bobo0609/p/6938012.html)


import語句匯入指定的模組時會執行3個步驟

1. 找到模組檔案:在模組搜尋路徑下搜尋模組檔案

  程式的主目錄

  PYTHONPATH目錄

  標準連結庫目錄


2.編譯成位元組碼:檔案匯入時會編譯,因此,頂層檔案的.pyc位元組碼檔案在內部使用後會被丟棄,只有被匯入的檔案才會留下.pyc檔案

3.執行模組的代碼來建立其所定義的對象:模組檔案中的所有語句從頭至尾依次執行,而此步驟中任何對變數名的賦值運算,都會產生所得到的模組檔案的屬性

注意:模組只在第一次匯入時才會執行如上步驟,後續的匯入操作只不過是提取記憶體中已載入的模組對象,reload()可用於重新載入模組


 


包: 用於將一組模組歸併到一個目錄中,此目錄即為包,目錄名即為包名


包是一個有層次的檔案目錄結構,它定義了一個由模組和子包組成的Python應用執行環境


基於包,Python在執行模組匯入時可以指定模組的匯入路徑 import pack1.pack2.mod1


每個包內都必須有__init__.py檔案, __init__.py 可包含python代碼,但通常為空白,僅用於扮演包初始化、替目錄產生模組命名空間以及使用目錄匯入時實現from*行為的角色


python的模組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.