import 初探 之 __import__() 、reload() 及受限腳本

逐漸起飛
        放下尼龍弦吉他,點下鼠標左鍵,退出 GP3 —— 即使是老版本,我還是比不上它的彈奏速度。但慶幸的是我還能勉強地跟上 Python 的節奏 —— 巨蟒的飛行速度。

        import 自古以來就沒有發生過什麼大的變化,只有在一次版本更替中引入了 as 關鍵詞。這種變化溫和到以至於我們常常會忘記 as 其實是在後來才加進來的,這正叫做隨風潛入夜潤物細無聲啊。

import string as string1, string as string2
from string import strip as strip1, strip as strip2

__import__()
嗯,import 總會去調這個玩藝的。也就是說你可以重載這個函數,讓 Python 在導入好東東之前先做出許多好玩的事情來:

old_imp = __buildins__.__import__
def new_imp(module_name, globals=None, locals=None, fromlist=[]):
 print module_name
 return old_imp(module_name, globals, locals, fromlist)

__buildins__.__import__ = new_imp

__import__() 的完全調用形式是 __import__(name, globals, locals, fromlist),name 即模塊名、其後是全局和局部變量,最後是在模塊中要導入的列表。比如:

__import__('string', globals(), locals(), ['join', 'split'])


當然,通常你可能會判斷一下該模塊是否已經導入過了。或者把你討厭的東西拒之門外。

reload()
這個聽起來有點像是我的那個金屬酒瓶。我與它在崗頂的那家小店鋪之中一見鍾情,結果花去我 140 ¥——當然威士忌要更貴一點。

reload 函數的意思就是舊瓶裝新酒了。比如我們已經 import something 了,但是外面的 something.py 模塊文件的內容突然改變、更新了,如果要享受新的 somethin.py 的好處,我們就需要 reload 一下了。

據說 reload 通常和一種神祕的儀式有關。差不多類似於這樣吧:

""" maillist.py
 向遠程 Mail 服務器查詢是否有新郵件。
 服務器返回一個 Python 模塊文件,把結果封裝在 show() 函數中。
"""

def
download_netobj(url, module_name): import urllib web_file = urllib.urlopen(url) buff = web_file.read() web_file.close() module_file = open(module_name + '.py', 'w') module_file.write(buff) module_file.close()
#查詢郵件
download_netobj( 'http://http://blog.czug.org/eishn/mail_list.cgi?user=eishn&pass=6star', 'mail_list') import mail_list mail_list.show()

#好的,過一會兒再查詢吧。
import time time.sleep(100)
#再次查詢
download_netobj( 'http://http://blog.czug.org/eishn/mail_list.cgi?user=eishn&pass=6star', 'mail_list')
reload(mail_list) mail_list.main()

reload() 通常對應的就是這種玩法。因爲模塊之所以會更新,大多數的情況是由於——模塊它自網上來。除了郵件服務,其他的玩法大同小異。自從對“程序混着數據傳來傳去”不再噁心之後,沈崴開始樂衷於此道,並開始自覺地傳道。

這就像是魔獸的地圖,既有靜態數據,又有許多 道具和人物。這些道具和人物的控制程序同時被封裝在假裝是地圖的那個文件裏。這樣那些遊戲們就可以動態的隨着地圖的不同改變更多的行爲了,比如添加更多地 圖特有的變態道具。

reload() 和 __import__() 一樣是可以重載的。

什麼是 __builtins__
__builtins__ 是一個名字空間,是系統自動生成的,其中的內容是直接可調用的。我們可以嘗試着導入一個叫做 __builtin__ 的模塊,如果發現模塊 __builtin__ 與名字空間 __builtins__ 中的內容無異,那麼我們正運行在一個無限制的 Python 執行環境下。

定製腳本執行環境
當然,重定義 __import__() 有着另一層深刻的含義 —— 如果你想定製一個自己的腳本執行環境的話。這讓我們想起 Zope 中的 "Python Script" 執行環境,只能使用 Zope 所允許的模塊,這相當酷。

簡單的做法,覆蓋掉腳本的 __builtins__.__import__ 函數,使之只能導入限定的模塊。

修改腳本的 __builtins__。當然我們已經知道了,如果想給它完全的執行環境可以把 module __builtin__ 的內容賦給腳本的 __builtins__ 名字空間 —— 其實系統總是默認地做了這件事情了。

好了,下面是一個訂製腳本執行環境的簡單例子:

execfile('script.py', {'__builtins__': {'__import__':lambda name, globals, locals, fromlist:None} } )

現在,script.py 這個腳本所能做的事情相當,相當有限了。

imp 模塊
imp 模塊是專業的導入功能定製模塊,而且它給人一較爲底層的映象。在網上可以找到一種叫做 knee.py 的腳本,它講了很多。

但是我從來沒有想過來使用這個模塊,因爲 imputil 工具模塊要更爲親和一點。使用 imp 或者 imputil 模塊可以讓你的程序於“無法在本地找到某一個模塊”時自動地區網上下載下來並導入,這顯得比上面 reload 一節中的那個郵件程序更爲聰明瞭。

欲練神功,揮刀自宮
在開始關於 import 的下面兩輯(之三、之四)之前,我想最好還是忘了本輯和第一集的內容吧,儘管他們是大廈的基礎,但是與新時代的 import 玩法似乎已經有些格格不入了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章