Python/模塊
在Python中,一個.py文件就稱之為一個模塊(Module)。使用模塊還可以避免函數名和變量名衝突。為了避免模塊名衝突,Python又引入了按目錄來組織模塊的方法,稱為包(Package)。引入了包以後,模塊名字就變為「包的文件夾名.模塊的文件名」。
模塊(module)
[編輯]模塊(module)可以是下述實體:
- Python文件(.py)
- Unix與Linux的共享對象,其後綴為.so
- Windows的DLL,後綴為.pyd
- 目錄,並應包含一個__init__.py文件。
任何模塊代碼的第一個字符串都被視為模塊的文檔注釋;
Python的搜索路徑sys.path,這是一個列表,包含了:
- 當前進程的根目錄
- PYTHONPATH 環境變量指定的路徑列表。
- Python 標準庫目錄列表。
- 路徑文件 (.pth) 保存的目錄 (通常放在 site-packages目錄下)
虛擬機按以下順序匹配目標模塊:
- py 源碼文件。
- pyc 字節碼文件。
- egg 包文件或目錄。
- so、dll、pyd 等擴展文件。
- 內置模塊。
- 其他。
Python模塊,可由import命令加載:
import module1[ as aliasname, module2[,... moduleN]
一個模塊只會被導入一次,不管執行了多少次import語句。模塊的名字追加到了當前符號表,但沒有把該模塊中的函數名稱寫入到當前符號表里。
從模塊中導入一個指定的部分到當前命名空間中,語法如下:
from modname import name1[ as alisasname, name2[, ... nameN]] from module2 import *
每個模塊有自己獨立的符號表,在模塊內部的函數當作全局符號表來使用。
模塊內部__xxx__這樣的變量是特殊變量,可以被直接引用,但是有特殊用途,如下列。類似_xxx和__xxx這樣的函數或變量就是非公開的(private),不應該被直接引用,即它們應視作模塊私有的名字。
- __name__屬性,其值為模塊名 <package>.<module>;當其值是'__main__'時,表明該模塊自身在運行,否則是被引入。
- __file__: 模塊完整⽂文件名。
- __dict__: 模塊 globals 名字空間。
- __doc__:模塊定義的文檔注釋
內置函數 dir() 以字符串列表的形式返回指定模塊內定義的所有名稱。
可以應對包不存在的異常:
try: import custommodule except ImportError: pass
sys.modules 是一個字典,它包含了從 Python 開始運行起,被導入的所有模塊。鍵字就是模塊名,鍵值就是模塊對象。列出已經導入的模塊:
print('\n'.join(sys.modules.keys()))
每個 Python 類都擁有一個內置的類屬性 __module__,它定義了這個類的模塊的名字。
from math import cos cos.__module__
卸載一個模塊:
del sys.modules["moduleName"]
可⽤用 imp.find_module() 獲取模塊的具體⽂文件信息:
imp.find_module("numpy")
import的本質
[編輯]import一個模塊module_name,實質上是創建一個同名變量(module_name),其類型是module。並在sys.modules中創建一個鍵值對。該模塊中的全局代碼也會被執行。
import一個模塊時,首先查看sys.modules是否已經有了該模塊。如果有了該模塊,則無操作。
顯然,在一個模塊中import另一個模塊,也是在sys.path中搜索。
包(package)
[編輯]包,是多個模塊的組織體系。目錄只有包含一個叫做 __init__.py 的文件(哪怕是空文件)才會被認作是一個包。否則,Python就把這個目錄當成普通目錄。__init__.py本身就是一個模塊,而它的模塊名就是包名。Python3中的包,__init__.py文件並不是必須的。__init__.py文件在包或內部模塊導入時自動執行,且僅執行一次。
可以有多級目錄,組成多級層次的包結構。
如果包定義文件 __init__.py 存在一個叫做 __all__ 的列表變量,那麼在使用 from package import * 的時候就把這個列表中的所有名字作為包內容導入。如果 __all__ 沒有定義,使用 from 包.子包 import *
這種語法的時候,不會導入包里的任何子模塊,只是把包和它裡面定義的所有內容導入進來。
包內部的一個模塊,可以如下引用這個包的其它模塊:
from . import another_module
import
[編輯]- 第一種用法:import module_name
- 第二種用法:from package_name import module_name
Python會在兩個地方尋找模塊或包:sys.path、運行文件所在的目錄。python3採用絕對導入,即嵌套的import是根據最外層的運行文件的所在目錄來導入。
相對導入的辦法:
- from . import module_name 導入和自己同目錄下的模塊
- from .package_name import module_name 導入和自己同目錄的包的模塊。
- from .. import module_name。導入上級目錄的模塊。
- from ..package_name import module_name。導入位於上級目錄下的包的模塊。每多一個點就多往上一層目錄。
如果運行文件使用了相對導入,就必須進入package_name所在目錄,然後用python -m package_name.module_name來啟動執行。
其他簡單但實用的用法:
import moudle_name as alias
from module_name import function_name, variable_name, class_name。使用逗號可以導入模塊中的多個元素。
有時候導入的元素很多,可以使用反斜槓來換行,官方推薦使用括號。
from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \
LEFT, DISABLED, NORMAL, RIDGE, END # 反斜杠换行
from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,
LEFT, DISABLED, NORMAL, RIDGE, END) # 括号换行(推荐)