python基礎教程:模塊高級技巧

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

在上一節中有一句話「接着咱們在這個文件所在目錄運行Python解釋器IPython」,不知道你們還記不記得。這就話背後隱含的意思是,在這個文件(模塊)目錄下,咱們才能夠import到這個模塊,不然會報錯,說找不到這個模塊。這裏,就涉及到了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獲得以下結果:ui

$ 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列表的第一個元素。符合上面三條原則的順序。spa

接下來咱們經過交互式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搜索模塊時先從當前文件夾開始。debug

以上兩種方法驗證的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.pathsys.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模塊的高級技巧

(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()不傳遞參數,則列出當前已經定義的全部名字:

In [1]: import my_first_module

In [2]: dir()
Out[2]: 
['In',
 'Out',
 '_',
 '__',
 '___',
 '__builtin__',
 '__builtins__',
 '__doc__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 '_dh',
 '_i',
 '_i1',
 '_i2',
 '_ih',
 '_ii',
 '_iii',
 '_oh',
 'exit',
 'get_ipython',
 'my_first_module',
 'quit']

用dir()能夠查看全部的內置類型、變量、函數等,方法是藉助標準模塊builtins

>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

Python模塊高級技巧總結

(1)Python的搜索路徑,順序必定要搞得清;
(2)編譯後的.pyc文件;(3)dir()內置函數查看模塊定義的名字。

相關文章
相關標籤/搜索