上一節,咱們講解了Python模塊的基礎知識,這一節咱們繼續深刻了解模塊的更多知識,從而讓你們全面瞭解、掌握和運用模塊到咱們實際的編程中。python
在上一節中有一句話「接着咱們在這個文件所在目錄運行Python解釋器IPython」,不知道你們還記不記得。這就話背後隱含的意思是,在這個文件(模塊)目錄下,咱們才能夠import到這個模塊,不然會報錯,說找不到這個模塊。這裏,就涉及到了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.path
。sys.path
是一個Python的列表結構,咱們能夠像修改列表那樣修改它,增長、刪除、修改路徑順序。好比,能夠經過sys.path.insert(0, 'my-module-path')
來把咱們本身寫的模塊的路徑放到搜索路徑的最前面,優先搜索本身的模塊。
*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
文件便可。
(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附帶了一個標準模塊庫。其中一些模塊內置在解釋器中,它們提供對不屬於語言核心但仍然內置的操做的訪問,以提升效率或提供對系統調用等操做系統原語的訪問。這些模塊的集合是一個配置選項,它也取決於底層平臺。例如,winreg
模塊僅在Windows系統上提供。一個值得注意的模塊是sys
,它內置於每一個Python解釋器中。
Python的標註模塊會在咱們從此的編程中不斷遇到和使用,具體的學習能夠在從此用到時再學習。你須要記住的一點是:當你寫Python代碼須要某些基本功能時,必定要先找找看是否已經有標準模塊存在,是否已經有人寫好了包含這些功能的模塊,最後纔要以爲本身要不要實現這些功能。
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']
(1)Python的搜索路徑,順序必定要搞得清;
(2)編譯後的.pyc
文件;(3)dir()內置函數查看模塊定義的名字。