除了包含函數定義外,模塊也可以包含可執行語句。這些語句一般用來初始化模塊。他們僅在?_第一次_?被導入的地方執行一次。[[1]](http://www.pythondoc.com/pythontutorial3/modules.html#id11)
每個模塊都有自己私有的符號表,被模塊內所有的函數定義作為全局符號表使用。因此,模塊的作者可以在模塊內部使用全局變量,而無需擔心它與某個用戶的全局變量意外沖突。從另一個方面講,如果你確切的知道自己在做什么,你可以使用引用模塊函數的表示法訪問模塊的全局變量,modname.itemname。
模塊可以導入其他的模塊。一個(好的)習慣是將所有的?import?語句放在模塊的開始(或者是腳本),這并非強制。被導入的模塊名會放入當前模塊的全局符號表中。
import?語句的一個變體直接從被導入的模塊中導入命名到本模塊的語義表中。例如:
~~~
>>> from fibo import fib, fib2
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
~~~
這樣不會從局域語義表中導入模塊名(如上所示,?fibo?沒有定義)。
甚至有種方式可以導入模塊中的所有定義:
~~~
>>> from fibo import *
>>> fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377
~~~
這樣可以導入所有除了以下劃線(?_?)開頭的命名。
需要注意的是在實踐中往往不鼓勵從一個模塊或包中使用?*?導入所有,因為這樣會讓代碼變得很難讀。不過,在交互式會話中這樣用很方便省力。
Note
出于性能考慮,每個模塊在每個解釋器會話中只導入一遍。因此,如果你修改了你的模塊,需要重啟解釋器;或者,如果你就是想交互式的測試這么一個模塊,可以用?reload()?重新加載,例如?reload(modulename)。
### 6.1.1\. 作為腳本來執行模塊
當你使用以下方式運行 Python 模塊時,模塊中的代碼便會被執行:
python fibo.py
模塊中的代碼會被執行,就像導入它一樣,不過此時?__name__?被設置為?"__main__"。這相當于,如果你在模塊后加入如下代碼:
~~~
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
~~~
就可以讓此文件像作為模塊導入時一樣作為腳本執行。此代碼只有在模塊作為 “main” 文件執行時才被調用:
~~~
$ python fibo.py 50
1 1 2 3 5 8 13 21 34
~~~
如果模塊被導入,不會執行這段代碼:
~~~
>>> import fibo
>>>
~~~
這通常用來為模塊提供一個便于測試的用戶接口(將模塊作為腳本執行測試需求)。
### 6.1.2\. 模塊的搜索路徑
導入一個叫?spam?的模塊時,解釋器先在當前目錄中搜索名為?spam.py?的文件。如果沒有找到的話,接著會到?sys.path?變量中給出的目錄列表中查找。?sys.path?變量的初始值來自如下:
* 輸入腳本的目錄(當前目錄)。
* 環境變量?PYTHONPATH?表示的目錄列表中搜索 (這和 shell 變量?PATH?具有一樣的語法,即一系列目錄名的列表)。
* Python 默認安裝路徑中搜索。
實際上,解釋器由?sys.path?變量指定的路徑目錄搜索模塊,該變量初始化時默認包含了輸入腳本(或者當前目錄),?PYTHONPATH?和安裝目錄。這樣就允許 Python 程序了解如何修改或替換模塊搜索目錄。需要注意的是由于這些目錄中包含有搜索路徑中運行的腳本,所以這些腳本不應該和標準模塊重名,否則在導入模塊時 Python 會嘗試把這些腳本當作模塊來加載。這通常會引發錯誤。請參見?[_標準模塊_](http://www.pythondoc.com/pythontutorial3/modules.html#tut-standardmodules)?以了解更多的信息。
### 6.1.3\. “編譯的” Python 文件
對于引用了大量標準模塊的短程序,有一個提高啟動速度的重要方法,如果在?spam.py?所在的目錄下存在一個名為?spam.pyc?的文件,它會被視為?spam?模塊的預“編譯”(?byte-compiled?,二進制編譯)版本。用于創建?spam.pyc?的這一版?spam.py?的修改時間記錄在?spam.pyc?文件中,如果兩者不匹配,.pyc?文件就被忽略。
通常你不需要為創建?spam.pyc?文件做任何工作。一旦?spam.py?成功編譯,就會嘗試生成對應版本的?spam.pyc?。如果有任何原因導致寫入不成功,生成的?spam.pyc?文件就會視為無效,隨后即被忽略。?spam.pyc?文件的內容是平臺獨立的,所以 Python 模塊目錄可以在不同架構的機器之間共享。
部分高級技巧:
* 以?_-O_?參數調用 Python 解釋器時,會生成優化代碼并保存在?.pyo?文件中。現在的優化器沒有太多幫助;它只是刪除了斷言(?assert?)語句。使用?_-O_?參數,?_所有_?的字節碼(?_bytecode_?)都會被優化;.pyc?文件被忽略,.py?文件被編譯為優化代碼。
* 向 Python 解釋器傳遞兩個?_-O_?參數(?_-OO_?)會執行完全優化的二進制優化編譯,這偶爾會生成錯誤的程序。現在的優化器,只是從字節碼中刪除了?__doc__?符串,生成更為緊湊的?.pyo?文件。因為某些程序依賴于這些變量的可用性,你應該只在確定無誤的場合使用這一選項。
* 來自?.pyc?文件或?.pyo?文件中的程序不會比來自?.py?文件的運行更快;.pyc?或?.pyo?文件只是在它們加載的時候更快一些。
* 通過腳本名在命令行運行腳本時,不會將為該腳本創建的二進制代碼寫入?.pyc?或?.pyo?文件。當然,把腳本的主要代碼移進一個模塊里,然后用一個小的啟動腳本導入這個模塊,就可以提高腳本的啟動速度。也可以直接在命令行中指定一個?.pyc?或?.pyo?文件。
* 對于同一個模塊(這里指例程 spam.py --譯者),可以只有?spam.pyc?文件(或者?spam.pyc,在使用?_-O_?參數時)而沒有?spam.py?文件。這樣可以打包發布比較難于逆向工程的 Python 代碼庫。
* compileall?模塊可以為指定目錄中的所有模塊創建?.pyc?文件(或者使用?_-O_?參數創建?.pyo?文件)。
- Python 入門指南
- 1. 開胃菜
- 2. 使用 Python 解釋器
- 2.1. 調用 Python 解釋器
- 2.2. 解釋器及其環境
- 3. Python 簡介
- 3.1. 將 Python 當做計算器
- 3.2. 編程的第一步
- 4. 深入 Python 流程控制
- 4.1. if 語句
- 4.2. for 語句
- 4.3. range() 函數
- 4.4. break 和 continue 語句, 以及循環中的 else 子句
- 4.5. pass 語句
- 4.6. 定義函數
- 4.7. 深入 Python 函數定義
- 4.8. 插曲:編碼風格
- 5. 數據結構
- 5.1. 關于列表更多的內容
- 5.2. del 語句
- 5.3. 元組和序列
- 5.4. 集合
- 5.5. 字典
- 5.6. 循環技巧
- 5.7. 深入條件控制
- 5.8. 比較序列和其它類型
- 6. 模塊
- 6.1. 深入模塊
- 6.2. 標準模塊
- 6.3. dir() 函數
- 6.4. 包
- 7. 輸入和輸出
- 7.1. 格式化輸出
- 7.2. 文件讀寫
- 8. 錯誤和異常
- 8.1. 語法錯誤
- 8.2. 異常
- 8.3. 異常處理
- 8.4. 拋出異常
- 8.5. 用戶自定義異常
- 8.6. 定義清理行為
- 8.7. 預定義清理行為
- 9. 類
- 9.1. 術語相關
- 9.2. Python 作用域和命名空間
- 9.3. 初識類
- 9.4. 一些說明
- 9.5. 繼承
- 9.6. 私有變量
- 9.7. 補充
- 9.8. 異常也是類
- 9.9. 迭代器
- 9.10. 生成器
- 9.11. 生成器表達式
- 10. Python 標準庫概覽
- 10.1. 操作系統接口
- 10.2. 文件通配符
- 10.3. 命令行參數
- 10.4. 錯誤輸出重定向和程序終止
- 10.5. 字符串正則匹配
- 10.6. 數學
- 10.7. 互聯網訪問
- 10.8. 日期和時間
- 10.9. 數據壓縮
- 10.10. 性能度量
- 10.11. 質量控制
- 10.12. “瑞士軍刀”
- 11. 標準庫瀏覽 – Part II
- 11.1. 輸出格式
- 11.2. 模板
- 11.3. 使用二進制數據記錄布局
- 11.4. 多線程
- 11.5. 日志
- 11.6. 弱引用
- 11.7. 列表工具
- 11.8. 十進制浮點數算法
- 12. 接下來?
- 13. 交互式輸入行編輯歷史回溯
- 13.1. 行編輯
- 13.2. 歷史回溯
- 13.3. 快捷鍵綁定
- 13.4. 其它交互式解釋器
- 14. 浮點數算法:爭議和限制
- 14.1. 表達錯誤
- 15. 附錄
- 15.1. 交互模式