摘要:對象序列化從這篇文章粗略翻譯的模塊可以實現(xiàn)任意的對象轉(zhuǎn)換為一系列字節(jié)即序列化對象的算法。的文檔明確的表明它不提供安全保證。而利用則可以控制序列化的細節(jié)。
Python 對象序列化——pickle and cPickle
從這篇文章粗略翻譯的pickle and cPickle
pickle模塊可以實現(xiàn)任意的Python對象轉(zhuǎn)換為一系列字節(jié)(即序列化對象)的算法。這些字節(jié)流可以 被傳輸或存儲,接著也可以重構(gòu)為一個和原先對象具有相同特征的新對象。
cPickle模塊實現(xiàn)了同樣的算法,但它是用c而不是python。因此,它比python實現(xiàn)的快上好幾倍, 但是不允許使用者去繼承Pickle。如果繼承對于你的使用不是很重要,那么你大可以使用cPickle。
Woring: pickle的文檔明確的表明它不提供安全保證。所以慎用pickle來作為內(nèi)部進程通信或者數(shù)
據(jù)存儲,也不要相信那些你不能驗證安全性的數(shù)據(jù)。
通常優(yōu)先試用 cPickle,只有當 cPickle 無法正常 import 的時候,采用 pickle 來替代。
try: import cPickle as pickle except: import pickleEncoding and Decoding Data in Strings
第一個示例是將數(shù)據(jù)結(jié)構(gòu)編碼為字符串,然后輸出到控制臺。例子中數(shù)據(jù)結(jié)構(gòu)完全由基本類型組成。pickle 可以編碼任意類的實例,就像下面栗子中演示的那樣:用 pickle.dumps() 來創(chuàng)建對象的字符串表示。
try: import cPickle as pickle except: import pickle import pprint data = [ { "a":"A", "b":2, "c":3.0 } ] print "DATA:", pprint.pprint(data) data_string = pickle.dumps(data) print "PICKLE:", data_string
pickle 默認試用 ASSCII 字符串來進行編碼解碼。也支持效率更高的二進制格式,但是下面的例子為了方便閱讀,還是使用了 ASSCII 碼。
$ python pickle_string.py DATA:[{"a": "A", "b": 2, "c": 3.0}] PICKLE: (lp1 (dp2 S"a" S"A" sS"c" F3 sS"b" I2 sa.
數(shù)據(jù)被序列化之后,你就可以將他寫入文件、socket、pipe、etc.然后你可以讀取文件并unpickle 這些數(shù)據(jù)來構(gòu)造一個新的對象。
try: import cPickle as pickle except: import pickle import pprint data1 = [ { "a":"A", "b":2, "c":3.0 } ] print "BEFORE:", pprint.pprint(data1) data1_string = pickle.dumps(data1) data2 = pickle.loads(data1_string) print "AFTER:", pprint.pprint(data2) print "SAME?:", (data1 is data2) print "EQUAL?:", (data1 == data2)
如同例子中演示的那樣,新的對象與之前的對象相等,但是并不是同一個對象。
Working with Streams
$ python pickle_unpickle.py BEFORE:[{"a": "A", "b": 2, "c": 3.0}] AFTER:[{"a": "A", "b": 2, "c": 3.0}] SAME?: False EQUAL?: True
除了 dumps() 跟 loads(), pickle 還有其他比較方便的方法來操作類文件流。可以同時寫入多個對象到一個 stream 中,然后對象數(shù)量與大小的時候從 stream 讀取他們。
try: import cPickle as pickle except: import pickle import pprint from StringIO import StringIO class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) l.reverse() self.name_backwards = "".join(l) return data = [] data.append(SimpleObject("pickle")) data.append(SimpleObject("cPickle")) data.append(SimpleObject("last")) # Simulate a file with StringIO out_s = StringIO() # Write to the stream for o in data: print "WRITING: %s (%s)" % (o.name, o.name_backwards) pickle.dump(o, out_s) out_s.flush() # Set up a read-able stream in_s = StringIO(out_s.getvalue()) # Read the data while True: try: o = pickle.load(in_s) except EOFError: break else: print "READ: %s (%s)" % (o.name, o.name_backwards)
上面例子中使用了 StringIO 緩沖區(qū)來模擬streams,這樣我們在建立可讀流的時候可以玩一些技巧。一些接單的數(shù)據(jù)庫格式也可以使用 pickles 來存儲數(shù)據(jù),當然,如果試用 shelve 來存儲會更加簡單。
$ python pickle_stream.py WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal) READ: pickle (elkcip) READ: cPickle (elkciPc) READ: last (tsal)
除了存儲數(shù)據(jù),pickles 用來做內(nèi)部通信的機會也很多。舉個例子:用 os.fork() 和 os.pipe() 可以建立一個工作進程,然后這個進程會從管道中讀取數(shù)據(jù)并把結(jié)果傳遞給另外一個管道。因為這些代碼是用來管理worker pool 跟 發(fā)送任務(wù)跟接受任務(wù)的,沒有什么特殊的內(nèi)容,所以這些核心代碼可以被拿來重復(fù)利用。如果你在試用 pipe 或者 sockets,那么在 dumping完對象之后,不要忘記刷新它們并通過其間的連接將數(shù)據(jù)推送到另外一個進程。如果你不想自己寫 worker pool manager 的話,可以看一下multiprocessing。
Problems Reconstructing Objects需要注意的是,在序列化實例的時候,我們只是對于數(shù)據(jù)來進行序列化,而無法對類的定義進行序列化。
下面的栗子:
try: import cPickle as pickle except: import pickle import sys class SimpleObject(object): def __init__(self, name): self.name = name l = list(name) l.reverse() self.name_backwards = "".join(l) return if __name__ == "__main__": data = [] data.append(SimpleObject("pickle")) data.append(SimpleObject("cPickle")) data.append(SimpleObject("last")) try: filename = sys.argv[1] except IndexError: raise RuntimeError("Please specify a filename as an argument to %s" % sys.argv[0]) out_s = open(filename, "wb") try: # Write to the stream for o in data: print "WRITING: %s (%s)" % (o.name, o.name_backwards) pickle.dump(o, out_s) finally: out_s.close()
運行的時候,這個腳本會以命令行中給出的參數(shù)創(chuàng)建一個文件。
$ python pickle_dump_to_file_1.py test.dat WRITING: pickle (elkcip) WRITING: cPickle (elkciPc) WRITING: last (tsal)
下面是一個會報錯的栗子:
try: import cPickle as pickle except: import pickle import pprint from StringIO import StringIO import sys try: filename = sys.argv[1] except IndexError: raise RuntimeError("Please specify a filename as an argument to %s" % sys.argv[0]) in_s = open(filename, "rb") try: # Read the data while True: try: o = pickle.load(in_s) except EOFError: break else: print "READ: %s (%s)" % (o.name, o.name_backwards) finally: in_s.close()
這個報錯是因為沒有SimpleObject類。
$ python pickle_load_from_file_1.py test.dat Traceback (most recent call last): File "pickle_load_from_file_1.py", line 52, ino = pickle.load(in_s) AttributeError: "module" object has no attribute "SimpleObject"
我們通過從原來的腳本中import SimpleObject來修正上面的錯誤。
在上面文件中的增加下面一行:
from pickle_dump_to_file_1 import SimpleObject
$ python pickle_load_from_file_2.py test.dat READ: pickle (elkcip) READ: cPickle (elkciPc) READ: last (tsal)
像sockets, file handles, database connections ...這些數(shù)據(jù)類型是無法被序列化的,我們在處理類似數(shù)據(jù)類型的時候不得不特殊處理。而利用pickle protocol 則可以控制序列化的細節(jié)。
class Data(object): def __init__(self, x, y): self._x = x self._y = y def __getstate__(self): d = self.__dict__.copy() del d["_y"] return d def __setstate__(self, state): self.__dict__.update(state) d = Data(10, 20) s = cPickle.dumps(d, 2) d2 = cPickle.loads(s) ##d2.__dict__ ##{"_x": 10}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/37359.html
摘要:使用來創(chuàng)建一個表示該對象值的字符串。數(shù)據(jù)被序列化以后,你可以將它們寫入文件套接字管道等等中。如果你使用管道或者套接字,在通過連至另一端的連接傾倒所有對象推送數(shù)據(jù)之后,別忘了沖洗。 目的:Python對象序列化 可用性:pickle至少1.4版本,cPickle 1.5版本以上 pickle模塊實現(xiàn)了一種算法,將任意一個Python對象轉(zhuǎn)化成一系列字節(jié)(byets)。此過程也調(diào)用了s...
摘要:重構(gòu)對象的問題當與你自己的類一起工作時,你必須保證類被腌漬出現(xiàn)在讀取的進程的命名空間中。因為使用值而不能被腌漬的類,可以定義和來返回狀態(tài)的一個子集,才能被腌漬。腌漬和反腌漬該圖來創(chuàng)建一個結(jié)點集合。 承接上文 pickle和cPickle:Python對象的序列化(上) 。 重構(gòu)對象的問題 當與你自己的類一起工作時,你必須保證類被腌漬出現(xiàn)在讀取pickle的進程的命名空間中。...
摘要:反序列化安全問題一這一段時間使用做開發(fā),使用了存儲,閱讀了源碼,發(fā)現(xiàn)在存儲到過程中,利用了模塊進行序列化以及反序列化正好根據(jù)該樣例學(xué)習(xí)一波反序列化相關(guān)的安全問題,不足之處請各位表哥指出。 Python 反序列化安全問題(一) 這一段時間使用flask做web開發(fā),使用了redis存儲session,閱讀了flask_session源碼,發(fā)現(xiàn)在存儲session到redis過程中,利用了...
摘要:利用標準庫中的的模塊可以將對象轉(zhuǎn)換為一種可以傳輸或存儲的格式。主要方法模塊中有兩個主要函數(shù),它們是和。具體語法為返回一個字符串,而不是存入文件中。該方法用于反序列化,即將序列化的對象重新恢復(fù)成對象。除此之外,這兩個模塊的接口是幾乎完全相同。 對象存在于程序運行時的內(nèi)存中,當程序不再運行時或斷電關(guān)機時,這些對象便不再存在。我現(xiàn)在想把對象保存下來,方便以后使用,這就是持久化技術(shù)。利用 py...
摘要:默認為或者說,是以格式保存對象如果設(shè)置為或者,則以壓縮的二進制格式保存對象。但是,要小心坑試圖增加一個坑就在這里當試圖修改一個已有鍵的值時沒有報錯,但是并沒有修改成功。要填平這個坑,需要這樣做多一個參數(shù)沒有坑了還用循環(huán)一下 pickle pickle是標準庫中的一個模塊,在Python 2中還有一個cpickle,兩者的區(qū)別就是后者更快。所以,下面操作中,不管是用import pick...
閱讀 3917·2021-09-09 09:33
閱讀 1773·2021-09-06 15:14
閱讀 1919·2019-08-30 15:44
閱讀 3076·2019-08-29 18:36
閱讀 3765·2019-08-29 16:22
閱讀 2095·2019-08-29 16:21
閱讀 2530·2019-08-29 15:42
閱讀 1648·2019-08-29 11:00