Python 為什麼不能序列化函數閉包?

Why cant Python closure be serialized?

搜了一下,好像 PHP 也有這個問題

http://stackoverflow.com/questions/13734224/exception-serialization-of-closure-is-not-allowed


其實就是pickle實現太傻逼而且還沒人去fix。。。有第三方的序列化庫是可以處理函數閉包的。

Parallelism and Serialization


沒什麼不能的,closure都在func_closure里,就是pickle懶得做而已。

我兩年前寫過一個庫,不光能序列化閉包,調用的其他函數和全局變數都能給一起序列化了。

Husky/function_husky.py at master · Tefx/Husky · GitHub

不過當時實現地比較簡單後來也不怎麼寫Python了所以我也不記得有沒有東西沒考慮了還有如果有Bug的話不用告訴我了。。。

嗯哼~


pickle不允許將位元組碼序列化,畢竟想想也知道太不安全了點,所以pickle當中的類和函數都必須以模塊路徑 + 函數或者類名的方式序列化,這樣就要求這個類或者函數可以從模塊中直接import出來。而閉包是在函數運行過程中創建出來的新函數,不是全局對象,所以pickle不可以序列化閉包。將位元組碼甚至運行堆棧序列化其實是可行的,但是應該只有同版本的Python才能交換吧。


理論上是感覺是能序列化的。純Python的bytecode就是string而已,可以自己去看。

當然也不會這麼簡單,除非是那種簡單的函數,你還得把這個函數執行的環境給一併序列化了傳過去,萬一碰到一個依賴了C-Extension的就沒轍了,你總沒法把內存打包過去吧。

所以Pickle這麼二,但是依然沒人去修的原因,我個人認為是Function的序列化在簡單情況(函數自己和所有的依賴都是純Python的)下是可以的,但是一來是很昂貴,二來是沒法應對複雜的情況。如果真要將一段邏輯在不同的process之間分享,由程序猿自己來保證兩邊環境對等,然後share code在eval就好了。


閉包的問題,到Python 2.7 才有 local 關鍵字進行支持,你說的這個估計一時半會兒也實現不了……


其實是可以的。。。pickle不行。

但有很多第三方庫是可以的。


推薦閱讀:

Speak my true name, summon my constructor
為什麼lists在functional programming里很重要?
Erlang入門教程 - 6. Maps
我想自學haskell無其他語言基礎 我該怎麼學 有什麼推薦的教材嗎?

TAG:Python | 函數式編程 | 編譯原理 |