利用 PEP 263 做 Python Metaprogramming
Posted by tjwei on 星期四, 1月 31, 2008 with 2 comments
Python 有一個功能(PEP 236),就是指定 source code 的 encoding,所以我們能夠方便的用 big5 碼、utf-8 碼寫程式。
比方檔案 u8.py
比方檔案 u8.py
# encoding: bbx
print "Origninal program"
就代表著 source code 的編碼是 bbx。
當然 bbx 這個編碼是不存在的,你執行個程式會發生錯誤。但也正是因為他不存在,所以能夠讓我們利用,比方下面的 bbx.py
因為 u8.py 設定的編碼方式是 bbx,所以 python 會根據 bbx.py 新定義的的 readline 來讀取 u8.py 檔案。
bbx.py 的編碼方式基本上是 big5,但是多了一個變化,會在檔案後面多加上三行程式碼。
所以執行 bbx.py 之後,除了正常的 execfile u8.py 外,最後還會多加上行。
我們還可以把 bbx.py 放入 site-package 目錄中,並且在 site-package 目錄下建立 bbx.pth,裡面放入一行
理論上,你可以用 readline 餵 python 吃任何東西。比方說,也許你的編碼器可以把 Lua 程式碼轉成 python 程式碼,可以把 java 轉成 python 程式碼,可以把把中文程式語言轉成 python,可以利用像是 easy extend 增加 python 的功能,或者簡單一點,把所有的內建 type 如 string, long, int 換成 proxy type, 讓你能如做比方做 "aaa".x=3 這類事情。
唯一的差別是,你不用 python fiber.py u8.py 或者 zhpy u8.py 這樣來執行你的程式,你直接 python u8.py 就能執行的你程式了。
更好的是, execfile, import 可以直接用,你的程式碼完全是合法的 python 程式(算是吧)。
當然 bbx 這個編碼是不存在的,你執行個程式會發生錯誤。但也正是因為他不存在,所以能夠讓我們利用,比方下面的 bbx.py
指定了 encoding bbx 的解碼方式,然後讓 python 執行 u8.py。import encodings,codecs
from encodings import big5
class reader(big5.StreamReader):
def readline(self, size=None, keepends=True):
rtn=big5.StreamReader.readline(self,size)
if not rtn:
rtn = u'%s\n'%extra.pop() if extra else u''
#print [rtn]
return rtn
def search_function(s):
if s=="bbx":
b5=encodings.search_function("big5")
return codecs.CodecInfo( name='bbx', encode=b5.encode,
decode=b5.decode,
incrementalencoder=b5.incrementalencoder,
incrementaldecoder=b5.incrementaldecoder,
streamreader=reader,
streamwriter=b5.streamwriter)
return None
extra=u"""
print '.........start..........'
print 'Extra lines'
print '..........end...........'
""".split("\n")
extra.reverse()
codecs.register(search_function)
if __name__=="__main__":
execfile("u8.py")
因為 u8.py 設定的編碼方式是 bbx,所以 python 會根據 bbx.py 新定義的的 readline 來讀取 u8.py 檔案。
bbx.py 的編碼方式基本上是 big5,但是多了一個變化,會在檔案後面多加上三行程式碼。
所以執行 bbx.py 之後,除了正常的 execfile u8.py 外,最後還會多加上行。
我們還可以把 bbx.py 放入 site-package 目錄中,並且在 site-package 目錄下建立 bbx.pth,裡面放入一行
import bbx這樣,python 在執行自動會註冊 bbx 這個編碼,這樣,我們就能直接用 python 執行 u8.py 這個檔案了。
理論上,你可以用 readline 餵 python 吃任何東西。比方說,也許你的編碼器可以把 Lua 程式碼轉成 python 程式碼,可以把 java 轉成 python 程式碼,可以把把中文程式語言轉成 python,可以利用像是 easy extend 增加 python 的功能,或者簡單一點,把所有的內建 type 如 string, long, int 換成 proxy type, 讓你能如做比方做 "aaa".x=3 這類事情。
唯一的差別是,你不用 python fiber.py u8.py 或者 zhpy u8.py 這樣來執行你的程式,你直接 python u8.py 就能執行的你程式了。
更好的是, execfile, import 可以直接用,你的程式碼完全是合法的 python 程式(算是吧)。
Categories: python
2 意見:
你這個想法相當有意思。我很感興趣。但是下載了源代碼後,運行所有的demo,都出現這樣的錯誤:
SyntaxError: encoding problem: with BOM
我的運行環境:ubuntu7.04, python2.5
謝謝你的反應。
的確有 bug,我想你如果有將 site-packages cp 過去的話,而且不是用 root 執行的話,應該是有幾個檔案權限不能 read 的關係。
另外還找到幾個 stdio hook 的問題,我也解決了,現在更新了,請重新下載修正後的 0.11 版本,謝謝你的反應。
http://tzerjen.googlepages.com/MagicCodec_0.11.tgz
張貼留言