如何在 Python 把 function 序列化?
在 Python 開發過程中,我們經常需要將不同類型的物件進行序列化,以便於存儲或通過網絡進行傳輸。對於基本數據類型和容器類型,這通常是一個直接的過程。然而,當涉及到更複雜的物件,如函數時,事情就變得有些棘手。
解法是利用 marshal 把 bytecode 轉成字串,就可以將之 Pickling。 marshal
模組提供了一個用於序列化和反序列化 Python 物件的介面。這個模組主要用於 Python 的 .pyc
文件,即編譯過的 Python 源碼文件。marshal 模組的主要功能是將 Python 物件轉換為字串(序列化),以及將這些字串還原為 Python 物件(反序列化)。
Pickling
Python 中的 pickling 是一種序列化過程,它將任何 Python 物件轉換為字節流。這個過程通過 pickle 模組實現,允許物件被保存到文件或通過網絡傳輸,並且可以在稍後被完整地恢復或“unpickled”。這對於數據持久化、深度複製物件或在不同 Python 程序之間傳輸複雜數據結構非常有用。
- 序列化(Pickling):將 Python 物件轉換為一個字節流的過程稱為 pickling。這通常是通過 pickle.dump() 函數實現的,該函數接受一個物件和一個文件物件作為參數,並將物件寫入文件。
- 反序列化(Unpickling):將 pickled 的字節流轉換回原始 Python 物件的過程稱為 unpickling。這通常是通過
pickle.load()
函數實現的,該函數從文件中讀取 pickled 的字節流並將其轉換回物件。
把 Function 轉成 Pickled string
import pickle
import marshal
maintask_bytecode = marshal.dumps(maintask_callback.func_code)
output = {
'maintask_bytecode': maintask_bytecode,
'maintask_defaults': maintask_defaults,
'maintask_args': maintask_args}
print pickle.dumps(output)
把Pickled string轉成function
import sys
import types
import marshal
import pickle
## \brief reconstruct function from bytecode
# \param func_bytecode str marshaled bytecode of func_code
# \param func_default dict func_defaults
# \return Function
def reconstruct_function(func_bytecode, func_defaults):
func_code = marshal.loads(func_bytecode)
return types.FunctionType(func_code, globals(), func_code.co_name,
func_defaults)
string = sys.stdin.read()
received = pickle.loads(string)
callback = reconstruct_function(received['maintask_bytecode'],
received['maintask_defaults'])
print callback(maintask_args)
這個技巧多用於要做語言互交互的情境,比如說在 Shell Script 跟 Python 之間互相調用對方的變數,函數。像是下面這段源碼, 就是讓 Shell Script 跟 Python 透過 Shell 的管道傳遞參數跟結果。
$ awk '{print $2}' /etc/apt/sources.list | grep http | \
boliau-readstdin | boliau-lines | \
boliau-map --command "lambda e: e.count('u')" | \
boliau-py-call sum | boliau-print
141
如果你對這很感興趣,可以閱讀我寫的boliau 的原始碼了解細節。