python基礎篇:模塊的高級技巧

Python 腳本語言 平地摔VS天然呆 2019-06-05
python基礎篇:模塊的高級技巧

上一節,我們講解了Python模塊的基礎知識,這一節我們繼續深入瞭解模塊的更多知識,從而讓大家全面瞭解、掌握和運用模塊到我們實際的編程中。

在上一節中有一句話“接著我們在這個文件所在目錄運行Python解釋器IPython”,不知道大家還記不記得。這就話背後隱含的意思是,在這個文件(模塊)目錄下,我們才可以import到這個模塊,否則會報錯,說找不到這個模塊。這裡,就涉及到了Python模塊的搜索路徑。

python基礎篇:模塊的高級技巧

Python模塊的搜索路徑

當一個名為mylib的模塊被導入時,解釋器首先搜索內置模塊是不是有該名字的模塊。

如果沒有找到,接著搜索sys.path列出的目錄下面是不是有名為mylib的模塊。

sys.path的初始化按以下幾個路徑的順序:

(1)包含輸入腳本的目錄,如果沒有輸入腳本則是當前目錄;

(2)環境變量PYTHONPATH(一個目錄名稱的列表);

(3)Python庫的安裝目錄。

下面我們來驗證一下sys.path所包含的路徑,編寫一個Python文件initpath.py如下:

# Author: veelion
# file: initpath.py
import sys
print('\n'.join(sys.path))

命令行下運行:python3 initpath.py得到如下結果:

$ python mylib.py
/home/veelion/p2/tutorial/md_Python/codes
/home/veelion/.virtualenvs/py3.7/lib/python37.zip
/home/veelion/.virtualenvs/py3.7/lib/python3.7
/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload
/usr/lib/python3.7
/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages

我們可以發現,initpath.py所在的目錄是sys.path列表的第一個元素。符合上面三條原則的順序。

接下來我們通過交互式Python解釋器來看看sys.path,運行CPython解釋器再導入sys:

>>> import sys
>>> sys.path
['', '/home/veelion/.virtualenvs/py3.7/lib/python37.zip', '/home/veelion/.virtualenvs/py3.7/lib/python3.7', '/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload', '/usr/lib/python3.7', '/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages']

細心的小猿可以發現,sys.path的第一項是個空字符串,和運行腳本方式下的第一項——當前路徑不一樣。為什麼會是空字符串呢?

這是因為,當交互式運行Python解釋器時(或者腳本是從標註輸入讀取的),可以認為傳給解釋器的腳本文件路徑為空,那麼就把sys.path[0]設置為空字符串,它告訴Python搜索模塊時先從當前文件夾開始。

以上兩種方法驗證的sys.path都符合預期,然而IPython有點例外。

In [1]: import sys
In [2]: sys.path
Out[2]:
['/home/veelion/.virtualenvs/py3.7/bin',
'/home/veelion/.virtualenvs/py3.7/lib/python37.zip',
'/home/veelion/.virtualenvs/py3.7/lib/python3.7',
'/home/veelion/.virtualenvs/py3.7/lib/python3.7/lib-dynload',
'/usr/lib/python3.7',
'',
'/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages',
'/home/veelion/.virtualenvs/py3.7/lib/python3.7/site-packages/IPython/extensions',
'/home/veelion/.ipython']

IPython 並沒有把當前路徑放在第一項。這樣就會導致你寫的模塊與系統模塊重名時,它import的是系統模塊而不是你寫的模塊,而前面兩種方式就是導入你寫的模塊而非系統模塊。這一點在使用IPython時要格外注意。

注意你可以在程序中修改sys.path。sys.path是一個Python的列表結構,我們可以像修改列表那樣修改它,增加、刪除、修改路徑順序。比如,可以通過sys.path.insert(0, 'my-module-path')來把我們自己寫的模塊的路徑放到搜索路徑的最前面,優先搜索自己的模塊。

編譯後的Python文件:*pyc

為了加速模塊的加載時間,Python會緩存已經編譯好的模塊,並把它們放在與模塊同級目錄下的__pycache__文件夾下面,編譯好的模塊的命名方式為:module.version.pyc,其中的version包含Python的版本號。比如:

$ ls __pycache__/
m1.cpython-36.pyc m2.cpython-36.pyc

cpython-36就是編譯這個模塊的Python信息:用CPython 3.6 進行編譯的。這種命名方式方便不同版本的Python編譯的模塊同時存在而不造成衝突。

Python在兩種情況下不檢查緩存。

其一,它總是重新編譯並且不存儲直接從命令行加載的模塊的結果。

其二,如果沒有模塊源碼文件,它不會檢查緩存。要支持非源(僅編譯)分發,已編譯的模塊必須位於源碼目錄中,並且不得有模塊源碼。

舉個例子理解一下這兩點:

(1)如果在命令行下運行python m1.py,Python總是從新編譯m1.py,但不會保存pyc文件,因為每次都有重新編譯就沒必要保存了。

(2)如果我們導入m1模塊時,搜索路徑目錄下只有m1.pyc而沒有m1.py文件,那就直接導入m1.pyc。這種方式適合把編譯好的pyc發佈給其他人而不是給它們源代碼,使用這種方式時,把.pyc文件從__pycache__中拷貝到.py文件相同的目錄下並刪掉.py文件即可。

python基礎篇:模塊的高級技巧

Python模塊的高級技巧

(1)模塊compileall可以把一個文件夾下所有的py文件編譯成.pyc文件。

它的使用很簡單,命令行運行的格式如下:

python -m compileall 文件夾或文件名

更多選項可以通過:python -m compileall -h查看。

(2)編譯成.pyc文件時,可以給Python命令兩個選項:-O和-OO,使得編譯後的文件更小。

-O 去除assert語句;

-OO 去除assert語句和__doc__ string。

根據情況來使用這兩個選項,用compileall編譯文件時加這個選項就是這樣子的:

python -O -m compileall 文件夾或文件名

生成的pyc文件名稱裡面有opt-標籤,-O的標籤是opt-,-OO的標籤就是opt-2。比如:

$ ls -F -1 __pycache__/
m1.cpython-36.opt-1.pyc
m1.cpython-36.opt-2.pyc
m1.cpython-36.pyc

(3).pyc和.py文件都不會使程序運行得更快(不會提高運行速度)。但是,.pyc文件能使加載速度更快,因為少了編譯的過程。

Python標準模塊

Python附帶了一個標準模塊庫。其中一些模塊內置在解釋器中,它們提供對不屬於語言核心但仍然內置的操作的訪問,以提高效率或提供對系統調用等操作系統原語的訪問。這些模塊的集合是一個配置選項,它也取決於底層平臺。例如,winreg模塊僅在Windows系統上提供。一個值得注意的模塊是sys,它內置於每個Python解釋器中。

Python的標註模塊會在我們今後的編程中不斷遇到和使用,具體的學習可以在今後用到時再學習。你需要記住的一點是:當你寫Python代碼需要某些基本功能時,一定要先找找看是否已經有標準模塊存在,是否已經有人寫好了包含這些功能的模塊,最後才要覺得自己要不要實現這些功能。

Python內置函數dir()

dir()用來查看模塊裡面定義的名字,包括:變量名,模塊名,函數名等等。

它返回一個list:

In [5]: import my_first_module
In [6]: dir(my_first_module)
Out[6]:
['MY_NAME',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'my_add',
'my_print']

如果調用dir()不傳遞參數,則列出當前已經定義的所有名字:

python基礎篇:模塊的高級技巧

用dir()可以查看所有的內置類型、變量、函數等,方法是藉助標準模塊builtins:

python基礎篇:模塊的高級技巧

Python模塊高級技巧總結

(1)Python的搜索路徑,順序一定要搞得清;

(2)編譯後的.pyc文件;

(3)dir()內置函數查看模塊定義的名字。

做什麼事情都需要不斷地堅持下去,編程也一樣。現在python語言十分火熱,職場對python的需求也很高,薪資待遇都很棒。所以希望大家能夠堅持學習,‘剩’者為王,堅持下來的人才有資格稱王。如果你覺得本文對你的學習有幫助的話,不妨點個關注,我會持續更新。

相關推薦

推薦中...