要使用模塊和庫,需要先導入。
**Python之禪**
```
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
```
導入系統是相當復雜的,不過你可能已經了解了一些基本知識。這里會介紹一些關于這一子系統的內部機理。
`sys`模塊包含許多關于Python導入系統的信息。首先,當前可導入的模塊列表可以通過`sys.moudle`變量獲取。它是一個字典,其中鍵(key)是模塊名字,對應的值(value)是模塊對象。
```
>>> sys.modules['os']
<module 'os' from '/usr/lib/python2.7/os.pyc'>
```
許多模塊是內置的,這些內置的模塊在`sys.builtin_module_names`中列出。內置的模塊可以根據傳入Python構建系統的編譯選項的不同而變化。
導入模塊時,Python會依賴一個路徑列表。這個列表存儲在`sys.path`變量中,并且告訴Python去哪里搜索要加載的模塊。可以在代碼中修改這個列表,根據需要添加或刪除路徑,也可以通過編寫Python代碼直接修改環境變量`PYTHONPATH`。下面的方法幾乎是相等的[①](#anchor21)。
```
>>> import sys
>>> sys.path.append('/foo/bar')
$ PYTHONPATH=/foo/bar python
>>> import sys
>>> '/foo/bar' in sys.path
True
```
在`sys.path`中的順序很重要,因為需要遍歷這個列表來尋找請求的模塊。
也可以通過自定義的導入器(importer)對導入機制進行擴展。Hy[②](#anchor22)正是利用這種技術告訴Python如何導入其他非標準的`.py`或者`.pyc`文件的。
顧名思義,導入鉤子機制是由PEP 302(<http://www.python.org/dev/peps/pep-0302/>)定義的[③](#anchor23)。它允許擴展標準的導入機制,并對其進行預處理,也可以通過追加一個工廠類到`sys.path_hooks`來添加自定義的模塊查找器(finder)。
模塊查找器對象必須有一個返回加載器對象的`find_module(fullname, path=None)`方法,這個加載器對象必須包含一個負責從源文件中加載模塊的`load_module(fullname)`方法。
為了進一步說明,下面給出了Hy利用自定義的導入器導入`.hy`而不是`.py`結尾的源文件的方法,見示例2.1。
**示例2.1 Hy模塊導入器**
```
class MetaImporter(object):
def find_on_path(self, fullname):
fls = ["%s/__init__.hy", "%s.hy"]
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
for fp in fls:
composed_path = fp % ("%s/%s" % (pth, dirpath))
if os.path.exists(composed_path):
return composed_path
def find_module(self, fullname, path=None):
path = self.find_on_path(fullname)
if path:
return MetaLoader(path)
sys.meta_path.append(MetaImporter())
```
一旦路徑被確定是有效的且指向了一個模塊,就會返回一個`MetaLoader`對象。
**Hy模塊加載器**
```
class MetaLoader(object):
def __init__(self, path):
self.path = path
def is_package(self, fullname):
dirpath = "/".join(fullname.split("."))
for pth in sys.path:
pth = os.path.abspath(pth)
composed_path = "%s/%s/__init__.hy" % (pth, dirpath)
if os.path.exists(composed_path):
return True
return False
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
if not self.path:
return
sys.modules[fullname] = None
mod = import_file_to_module(fullname, self.path) ?
ispkg = self.is_package(fullname)
mod.__file__ = self.path
mod.__loader__ = self
mod.__name__ = fullname
if ispkg:
mod.__path__ = []
mod.__package__ = fullname
else:
mod.__package__ = fullname.rpartition('.')[0]
sys.modules[fullname] = mod
return mod
```
? `import_file_to_module`讀取一個Hy源文件,將其編譯成Python代碼,并返回一個Python模塊對象。
`uprefix`模塊(<https://pypi.python.org/pypi/uprefix>)是這個功能起作用的另一個好的例子。Python 3.0到3.2并沒有像Python 2中用來表示Unicode字符串的`u`前綴[④](#anchor24),這個模塊通過在編譯前刪除字符串的前綴`u`來確保在2.x和3.x之間的兼容性。
- - - - - -
[①](#ac21) 說“幾乎”是因為路徑并不會被放在列表的同一級上,盡管根據你的使用情況它可能并不重要。
[②](#ac22) Hy是Python上的Lisp實現,會在11.2節介紹。
[③](#ac23) 自Python 2.3版本實現的新導入鉤子機制。
[④](#ac24) 它在Python 3.3中又被加了回來。
- 內容提要
- 中文版序
- 前言
- 第1章 項目開始
- 1.1 Python版本
- 1.2 項目布局
- 1.3 版本編號
- 1.4 編碼風格與自動檢查
- 1.5 Joshua Harlow訪談
- 第2章 模塊和庫
- 2.1 導入系統
- 2.2 標準庫
- 2.3 外部庫
- 2.4 框架
- 2.5 Doug Hellmann訪談
- 第3章 管理API變化
- Christophe de Vienne訪談
- 第4章 時區陷阱
- 第5章 文檔
- 5.1 Sphinx和reST入門
- 5.2 Sphinx模塊
- 5.3 擴展Sphinx
- 第6章 分發
- 6.1 簡史
- 6.2 使用pbr打包
- 6.3 Wheel格式
- 6.4 包的安裝
- 6.5 和世界分享你的成果
- 6.6 Nick Coghlan訪談
- 6.7 入口點
- 6.7.1 可視化的入口點
- 6.7.2 使用控制臺腳本
- 6.7.3 使用插件和驅動程序
- 第7章 虛擬環境
- 第8章 單元測試
- 8.1 基礎知識
- 8.2 fixture
- 8.3 模擬(mocking)
- 8.4 場景測試
- 8.5 測試序列與并行
- 8.6 測試覆蓋
- 8.7 使用虛擬環境和tox
- 8.8 測試策略
- 8.9 Robert Collins訪談
- 第9章 方法和裝飾器
- 9.1 創建裝飾器
- 9.2 Python中方法的運行機制
- 9.3 靜態方法
- 9.4 類方法
- 9.5 抽象方法
- 9.6 混合使用靜態方法、類方法和抽象方法
- 9.7 關于super的真相
- 第10章 函數式編程
- 10.1 生成器
- 10.2 列表推導
- 10.3 函數式函數的函數化
- 第11章 抽象語法樹
- 11.1 用抽象語法樹檢查來擴展flake8
- 11.2 Hy
- 11.3 Paul Tagliamonte訪談
- 第12章 性能與優化
- 12.1 數據結構
- 12.2 性能分析
- 12.3 有序列表和二分查找
- 12.4 namedtuple和slots
- 12.5 memoization
- 12.6 PyPy
- 12.7 通過緩沖區協議實現零復制
- 12.8 Victor Stinner訪談
- 第13章 擴展與架構
- 13.1 多線程的注意事項
- 13.2 多進程與多線程
- 13.3 異步和事件驅動架構
- 13.4 面向服務架構
- 第14章 RDBMS和ORM
- 14.1 用Flask和PostgreSQL流化數據
- 14.2 Dimitri Fontaine訪談
- 第15章 Python 3支持策略
- 15.1 語言和標準庫
- 15.2 外部庫
- 15.3 使用six
- 第16章 少即是多
- 16.1 單分發器
- 16.2 上下文管理器
- 第17章 延伸閱讀
- 版權信息
- 版權聲明
- 歡迎來到異步社區!
- 異步社區的來歷
- 社區里都有什么?
- 購買圖書
- 下載資源
- 與作譯者互動
- 靈活優惠的購書
- 紙電圖書組合購買
- 社區里還可以做什么?
- 提交勘誤
- 寫作
- 會議活動早知道
- 加入異步