Programming Python, 3rd Edition 翻譯最新版本見(jiàn):http://wiki.woodpecker.org.cn/moin/PP3eD
19.4. Pickled Objects 19.4. Pickle對(duì)象
Probably the biggest limitation of DBM keyed files is in what they can store: data stored under a key must be a simple text string. If you want to store Python objects in a DBM file, you can sometimes manually convert them to and from strings on writes and reads (e.g., with str and eval calls), but this takes you only so far. For arbitrarily complex Python objects such as class instances and nested data structures, you need something more. Class instance objects, for example, cannot be later re-created from their standard string representations. Custom to-string conversions are error prone and not general.
DBM 鍵控文件(DBM keyed file)最大的限制也許在于他們可以存儲(chǔ)的東西:一個(gè)鍵值下存儲(chǔ)的數(shù)據(jù)必須是個(gè)簡(jiǎn)單文本字符串。如果您想要在DBM文件中儲(chǔ)存Python對(duì)象,有時(shí)您 可以在讀寫的時(shí)候,手動(dòng)進(jìn)行與字符串的轉(zhuǎn)換(例如,用str和eval調(diào)用),但只能做到這樣。對(duì)任意復(fù)雜的Python對(duì)象,如類實(shí)例和嵌套的數(shù)據(jù)結(jié) 構(gòu),您需要更多的東西。例如,類實(shí)例對(duì)象以后無(wú)法從其標(biāo)準(zhǔn)字符串表達(dá)(string representation)重建。自定義的到字符串的轉(zhuǎn)換容易出錯(cuò),并且不通用。
The Python pickle module, a standard part of the Python system, provides the conversion step needed. It converts nearly arbitrary Python in-memory objects to and from a single linear string format, suitable for storing in flat files, shipping across network sockets between trusted sources, and so on. This conversion from object to string is often called serializationarbitrary data structures in memory are mapped to a serial string form.
Python 系統(tǒng)的標(biāo)準(zhǔn)部件,pickle模塊,提供了所需的轉(zhuǎn)換步驟。它可以將幾乎任意的Python內(nèi)存對(duì)象,轉(zhuǎn)換為單一線性的字符串格式,使之適于無(wú)格式文件存 儲(chǔ),或在可靠來(lái)源之間跨越網(wǎng)絡(luò)套接口傳輸?shù)鹊龋⒖煞聪蜣D(zhuǎn)換。這種從對(duì)象到字符串的轉(zhuǎn)換通常被稱為序列化(serialization):將內(nèi)存中的任意 數(shù)據(jù)結(jié)構(gòu)映射為串行字符串形式。
The string representation used for objects is also sometimes referred to as a byte stream, due to its linear format. It retains all the content and references structure of the original in-memory object. When the object is later re-created from its byte string, it will be a new in-memory object identical in structure and value to the original, though located at a different memory address. The re-created object is effectively a copy of the original.
對(duì)象的字符串表達(dá)由于其線性的格式,有時(shí)也被稱為字節(jié)流。它包含了原始內(nèi)存中對(duì)象的所有內(nèi)容和引用結(jié)構(gòu)。當(dāng)對(duì)象后來(lái)從其字節(jié)串重建時(shí),內(nèi)存中新建的對(duì)象與原對(duì)象具有相同的結(jié)構(gòu)和值,但位于不同的內(nèi)存地址。該重建對(duì)象實(shí)際上是原對(duì)象的復(fù)制。
Pickling works on almost any Python datatypenumbers, lists, dictionaries, class instances, nested structures, and moreand so is a general way to store data. Because pickles contain native Python objects, there is almost no database API to be found; the objects stored are processed with normal Python syntax when they are later retrieved.
Pickle可用于幾乎所有的Python數(shù)據(jù)類型:數(shù)字、列表、字典、類實(shí)例、嵌套結(jié)構(gòu),等等,因此它是存儲(chǔ)數(shù)據(jù)的通用方法。因?yàn)閜ickle包含的是Python本地對(duì)象,所以幾乎沒(méi)有數(shù)據(jù)庫(kù)的API;對(duì)象存儲(chǔ)與處理及后來(lái)的提取用的都是通常的Python語(yǔ)法。
19.4.1. Using Object Pickling
19.4.1. 使用對(duì)象pickle
Pickling may sound complicated the first time you encounter it, but the good news is that Python hides all the complexity of object-to-string conversion. In fact, the pickle module 's interfaces are incredibly simple to use. For example, to pickle an object into a serialized string, we can either make a pickler and call its methods or use convenience functions in the module to achieve the same effect:
第 一次聽(tīng)到pickle,可能覺(jué)得有點(diǎn)復(fù)雜,但好消息是,Python隱藏了所有從對(duì)象到字符串轉(zhuǎn)換的復(fù)雜性。事實(shí)上,pickle模塊的接口簡(jiǎn)單易用,簡(jiǎn) 直令人難以置信。例如,要pickle對(duì)象到一個(gè)序列化字符串,我們可以生成一個(gè)pickler,并調(diào)用其方法,或使用模塊中的便捷函數(shù)來(lái)達(dá)到相同的效 果:
P = pickle.Pickler( file)
Make a new pickler for pickling to an open output file object file. 生成一個(gè)新的pickler,用來(lái)pickle到一個(gè)打開(kāi)的輸出文件對(duì)象file。
P.dump( object)
Write an object onto the pickler's file/stream. 寫一個(gè)對(duì)象到pickler的文件/流。
pickle.dump( object, file)
Same as the last two calls combined: pickle an object onto an open file. 等同于上兩個(gè)調(diào)用的組合:pickle對(duì)象到一個(gè)打開(kāi)的文件。
string = pickle.dumps( object)
Return the pickled representation of object as a character string. 返回一個(gè)字符串作為已pickle對(duì)象的表達(dá)。
Unpickling from a serialized string back to the original object is similarboth object and convenience function interfaces are available:
從一個(gè)序列化字符串unpickle回原始對(duì)象是類似的,可以用對(duì)象也可以用便捷函數(shù)接口:
U = pickle.Unpickler( file)
Make an unpickler for unpickling from an open input file object file. 生成一個(gè)unpickler,用來(lái)從一個(gè)打開(kāi)的文件對(duì)象file unpickle。
object = U.load( )
Read an object from the unpickler's file/stream. 從unpickler的文件/流讀取一個(gè)對(duì)象。
object = pickle.load( file)
Same as the last two calls combined: unpickle an object from an open file. 等同于上兩個(gè)調(diào)用的組合:從一個(gè)打開(kāi)的文件unpickle一個(gè)對(duì)象。
object = pickle.loads( string)
Read an object from a character string rather than a file. 從字符串讀取一個(gè)對(duì)象,而不是從文件。
Pickler and Unpickler are exported classes. In all of the preceding cases, file is either an open file object or any object that implements the same attributes as file objects:
Pickler和Unpickler是導(dǎo)出類。在上述所有情況下,file是個(gè)已打開(kāi)的文件對(duì)象,或者是實(shí)現(xiàn)了以下文件對(duì)象屬性的任何對(duì)象:
Pickler calls the file's write method with a string argument.
Pickler會(huì)調(diào)用文件的write方法,參數(shù)是個(gè)字符串。
Unpickler calls the file's read method with a byte count, and readline without arguments.
Unpickler會(huì)調(diào)用文件的read方法,參數(shù)是字節(jié)數(shù),以及readline,無(wú)參數(shù)。
Any object that provides these attributes can be passed in to the file parameters. In particular, file can be an instance of a Python class that provides the read/write methods (i.e., the expected file-like interface). This lets you map pickled streams to in-memory objects with classes, for arbitrary use. For instance, the StringIO standard library module discussed in Chapter 3 provides classes that map file calls to and from in-memory strings.
任 何提供這些屬性的對(duì)象都可以作為file參數(shù)傳入。特別是,file可以是一個(gè)提供了讀/寫方法的Python類實(shí)例(即預(yù)期的類似文件的接口)。這讓您 可以用類映射pickle流到內(nèi)存對(duì)象,并可任意使用。例如,第3章討論的標(biāo)準(zhǔn)庫(kù)模塊StringIO提供的類,它們可映射文件調(diào)用到內(nèi)存字符串或反之。
This hook also lets you ship Python objects across a network, by providing sockets wrapped to look like files in pickle calls at the sender, and unpickle calls at the receiver (see the sidebar "Making Sockets Look Like Files," in Chapter 13, for more details). In fact, for some, pickling Python objects across a trusted network serves as a simpler alternative to network transport protocols such as SOAP and XML-RPC; provided that Python is on both ends of the communication (pickled objects are represented with a Python-specific format, not with XML text).
該 掛鉤也可以讓您通過(guò)網(wǎng)絡(luò)傳輸Python對(duì)象,只要封裝套接口,使之看上去像發(fā)送端pickle調(diào)用中的文件,以及像接收端unpickle調(diào)用中的文件 (詳見(jiàn)第13章側(cè)欄“使套接口看上去像文件”)。事實(shí)上,對(duì)一些人來(lái)說(shuō),pickle Python對(duì)象并在一個(gè)值得信賴的網(wǎng)絡(luò)上傳輸,是替代如SOAP和XML-RPC之類網(wǎng)絡(luò)傳輸協(xié)議的一個(gè)簡(jiǎn)單方法;只要通信的兩端都有Python(被 pickle的對(duì)象是用Python專有的格式表達(dá)的,而不是用XML文本)。
19.4.2. Picking in Action
19.4.2. Pickle實(shí)戰(zhàn)
In more typical use, to pickle an object to a flat file, we just open the file in write mode and call the dump function:
典型的使用情況是,pickle對(duì)象到無(wú)格式文件,我們只需以寫模式打開(kāi)文件,并調(diào)用dump函數(shù):
% python>>> table = {'a': [1, 2, 3], 'b': ['spam', 'eggs'], 'c': {'name':'bob'}}>>>>>> import pickle>>> mydb = open('dbase', 'w')>>> pickle.dump(table, mydb)
Notice the nesting in the object pickled herethe pickler handles arbitrary structures. To unpickle later in another session or program run, simply reopen the file and call load:
注意這個(gè)被pickle對(duì)象中的嵌套:pickler可以處理任意結(jié)構(gòu)。然后,在另一個(gè)會(huì)話或程序中unpickle,只要重新打開(kāi)該文件,并調(diào)用load:
% python>>> import pickle>>> mydb = open('dbase', 'r')>>> table = pickle.load(mydb)>>> table{'b': ['spam', 'eggs'], 'a': [1, 2, 3], 'c': {'name': 'bob'}}
The object you get back from unpickling has the same value and reference structure as the original, but it is located at a different address in memory. This is true whether the object is unpickled in the same or a future process. In Python-speak, the unpickled object is == but is not is:
unpickle所得的對(duì)象具有與原對(duì)象相同的值和引用結(jié)構(gòu),但它位于不同的內(nèi)存地址。無(wú)論在同一進(jìn)程或另一進(jìn)程unpickle,都是這樣。用Python的話來(lái)說(shuō),unpickle后的對(duì)象是“==”關(guān)系,但不是“is”關(guān)系:
% python>>> import pickle>>> f = open('temp', 'w')>>> x = ['Hello', ('pickle', 'world')] # list with nested tuple>>> pickle.dump(x, f)>>> f.close( ) # close to flush changes>>>>>> f = open('temp', 'r')>>> y = pickle.load(f)>>> y['Hello', ('pickle', 'world')]>>>>>> x == y, x is y(True, False)
To make this process simpler still, the module in Example 19-1 wraps pickling and unpickling calls in functions that also open the files where the serialized form of the object is stored.
為了讓這一過(guò)程更簡(jiǎn)單,例19-1中的模塊把pickle和unpickle調(diào)用封裝在函數(shù)中,在函數(shù)中同時(shí)還打開(kāi)文件,并將對(duì)象的序列化存儲(chǔ)在該文件中。
Example 19-1. PP3E\Dbase\filepickle.py
1 import pickle 2 3 def saveDbase(filename, object): 4 file = open(filename, 'w') 5 pickle.dump(object, file) # pickle to file 6 file.close( ) # any file-like object will do 7 8 def loadDbase(filename): 9 file = open(filename, 'r') 10 object = pickle.load(file) # unpickle from file 11 file.close( ) # re-creates object in memory 12 return object
To store and fetch now, simply call these module functions; here they are in action managing a fairly complex structure with multiple references to the same nested objectthe nested list called L at first is stored only once in the file:
現(xiàn)在,存儲(chǔ)和提取時(shí)只需調(diào)用這些模塊函數(shù);以下實(shí)例是個(gè)相當(dāng)復(fù)雜的結(jié)構(gòu),具有對(duì)同一嵌套對(duì)象的多重引用,該嵌套列表,即第1個(gè)L,在文件中只會(huì)保存一次:
C:\...\PP3E\Dbase>python>>> from filepickle import *>>> L = [0]>>> D = {'x':0, 'y':L}>>> table = {'A':L, 'B':D} # L appears twice>>> saveDbase('myfile', table) # serialize to fileC:\...\PP3E\Dbase>python>>> from filepickle import *>>> table = loadDbase('myfile') # reload/unpickle>>> table{'B': {'x': 0, 'y': [0]}, 'A': [0]}>>> table['A'][0] = 1 # change shared object>>> saveDbase('myfile', table) # rewrite to the fileC:\...\PP3E\Dbase>python>>> from filepickle import *>>> print loadDbase('myfile') # both L's updated as expected{'B': {'x': 0, 'y': [1]}, 'A': [1]}
Besides built-in types like the lists, tuples, and dictionaries of the examples so far, class instances may also be pickled to file-like objects. This provides a natural way to associate behavior with stored data (class methods process instance attributes) and provides a simple migration path (class changes made in module files are automatically picked up by stored instances). Here's a brief interactive demonstration:
除 了內(nèi)置的類型,如以上例子中的列表,元組和字典,類實(shí)例也可被pickle到類似文件的對(duì)象中。這提供了一個(gè)自然的方式來(lái)關(guān)聯(lián)行為與存儲(chǔ)的數(shù)據(jù)(類方法處 理實(shí)例的屬性),并提供了一條簡(jiǎn)單的遷移路徑(被存儲(chǔ)的實(shí)例將自動(dòng)獲得模塊文件中對(duì)類的更改)。以下是個(gè)簡(jiǎn)短的交互演示:
>>> class Rec: def _ _init_ _(self, hours): self.hours = hours def pay(self, rate=50): return self.hours * rate>>> bob = Rec(40)>>> import pickle>>> pickle.dump(bob, open('bobrec', 'w'))>>>>>> rec = pickle.load(open('bobrec'))>>> rec.hours40>>> rec.pay( )2000
We'll explore how this works in more detail in conjunction with shelves later in this chapteras we'll see, although the pickle module can be used directly, it is also the underlying translation engine in both shelves and ZODB databases.
我們將與本章下面的shelve一起詳細(xì)探討這是如此工作的。我們將會(huì)看到,雖然pickle模塊可直接使用,但它也是shelve和ZODB數(shù)據(jù)庫(kù)的底層翻譯引擎。
In fact, Python can pickle just about anything, except for:
事實(shí)上,Python可以pickle任何東西,除了:
Compiled code objects; functions and classes record just their names in pickles, to allow for later reimport and automatic acquisition of changes made in module files.
編譯的代碼對(duì)象;函數(shù)和類在pickle中只是記錄了它們的名字,以便后來(lái)重新導(dǎo)入和自動(dòng)獲取模塊文件中的更改。
Instances of classes that do not follow class importability rules (more on this at the end of the section "Shelve Files," later in this chapter).
不遵守類可導(dǎo)入規(guī)則(class importability rule)的類實(shí)例(本章后面“Shelve文件”一節(jié)的尾部有更多相關(guān)內(nèi)容)。
Instances of some built-in and user-defined types that are coded in C or depend upon transient operating system states (e.g., open file objects cannot be pickled).
用C編碼的或依賴于操作系統(tǒng)瞬態(tài)的一些內(nèi)置的和用戶定義類型的實(shí)例(例如,打開(kāi)的文件對(duì)象無(wú)法pickle)。
A PicklingError is raised if an object cannot be pickled.
如果對(duì)象不能pickle,會(huì)引發(fā)PickleError。
19.4.3. Pickler Protocols and cPickle
19.4.3. Pickler協(xié)議和cPickle
In recent Python releases, the pickler introduced the notion of protocolsstorage formats for pickled data. Specify the desired protocol by passing an extra parameter to the pickling calls (but not to unpickling calls: the protocol is automatically determined from the pickled data):
在最近的Python版本中,pickler推出了協(xié)議的概念:pickle數(shù)據(jù)的保存格式。通過(guò)pickle調(diào)用時(shí)傳入一個(gè)額外的參數(shù),可指定所需的協(xié)議(但unpickle調(diào)用不需要:協(xié)議是自動(dòng)從已pickle的數(shù)據(jù)確定的):
pickle.dump(object, file, protocol)
Pickled data may be created in either text or binary protocols. By default, the storage protocol is text (also known as protocol 0). In text mode, the files used to store pickled objects may be opened in text mode as in the earlier examples, and the pickled data is printable ASCII text, which can be read (it's essentially instructions for a stack machine).
Pickle 數(shù)據(jù)可以按文本協(xié)議或二進(jìn)制協(xié)議產(chǎn)生。默認(rèn)情況下,存儲(chǔ)協(xié)議是文本協(xié)議(也稱為0號(hào)協(xié)議)。在文本模式下,用來(lái)存儲(chǔ)pickle對(duì)象的文件可以用文本模式 打開(kāi),如上述的例子,并且pickle的數(shù)據(jù)是可打印的ASCII文本,并且是可讀的(這基本上是對(duì)堆棧機(jī)實(shí)現(xiàn)的指示)。
The alternative protocols (protocols 1 and 2) store the pickled data in binary format and require that files be opened in binary mode (e.g., rb, wb). Protocol 1 is the original binary format; protocol 2, added in Python 2.3, has improved support for pickling of new-style classes. Binary format is slightly more efficient, but it cannot be inspected. An older option to pickling calls, the bin argument, has been subsumed by using a pickling protocol higher than 0. The pickle module also provides a HIGHEST_PROTOCOL variable that can be passed in to automatically select the maximum value.
其 他協(xié)議(1號(hào)和2號(hào)協(xié)議 )以二進(jìn)制格式存儲(chǔ)pickle數(shù)據(jù),并要求文件以二進(jìn)制模式打開(kāi)(例如:rb、wb)。1號(hào)協(xié)議是原始二進(jìn)制格式;2號(hào)協(xié)議是Python 2.3增加的,它改善了對(duì)新型類pickle的支持。二進(jìn)制格式效率更高一點(diǎn),但它無(wú)法進(jìn)行查看。舊的pickle調(diào)用有一個(gè)選項(xiàng),即bin參數(shù),現(xiàn)已被 歸入使用大于0的協(xié)議。pickle模塊還提供了一個(gè)HIGHEST_PROTOCOL變量,傳入它可以自動(dòng)選擇最大的協(xié)議值。
One note: if you use the default text protocol, make sure you open pickle files in text mode later. On some platforms, opening text data in binary mode may cause unpickling errors due to line-end formats on Windows:
注意:如果您使用默認(rèn)的文本協(xié)議,以后請(qǐng)務(wù)必以文本模式打開(kāi)pickle文件。在一些平臺(tái)上,因?yàn)閃indows的行尾格式不同,以二進(jìn)制模式打開(kāi)文本數(shù)據(jù)可能會(huì)導(dǎo)致unpickle錯(cuò)誤:
>>> f = open('temp', 'w') # text mode file on Windows>>> pickle.dump(('ex', 'parrot'), f) # use default text protocol>>> f.close( ) >>>>>> pickle.load(open('temp', 'r')) # OK in text mode('ex', 'parrot')>>> pickle.load(open('temp', 'rb')) # fails in binaryTraceback (most recent call last): File "<pyshell#337>", line 1, in -toplevel- pickle.load(open('temp', 'rb')) ...lines deleted...ValueError: insecure string pickle
One way to sidestep this potential issue is to always use binary mode for your files, even for the text pickle protocol. Since you must open files in binary mode for the binary pickler protocols anyhow (higher than the default 0), this isn't a bad habit to get into:
回避這個(gè)潛在問(wèn)題的方法之一是,總是使用二進(jìn)制模式的文件,即使是用文本pickle協(xié)議。至少對(duì)于二進(jìn)制pickler協(xié)議(高于默認(rèn)0),您必須以二進(jìn)制模式打開(kāi)文件,所以這不是一個(gè)壞習(xí)慣:
>>> f = open('temp', 'wb') # create in binary mode>>> pickle.dump(('ex', 'parrot'), f) # use text protocol>>> f.close( )>>>>>> pickle.load(open('temp', 'rb'))('ex', 'parrot')>>> pickle.load(open('temp', 'r'))('ex', 'parrot')
Refer to Python's library manual for more information on the pickler. Also check out marshal, a module that serializes an object too, but can handle only simple object types. pickle is more general than marshal and is normally preferred.
請(qǐng)參考Python庫(kù)手冊(cè),以了解更多pickler的信息。另外,請(qǐng)查閱marshal,它也是一個(gè)序列化對(duì)象的模塊,但只能處理簡(jiǎn)單對(duì)象類型。pickle比marshal更通用,并通常是首選。
And while you are flipping (or clicking) through that manual, be sure to also see the entries for the cPickle modulea reimplementation of pickle coded in C for faster performance. You can explicitly import cPickle for a substantial speed boost; its chief limitation is that you cannot subclass its versions of Pickle and Unpickle because they are functions, not classes (this is not required by most programs). The pickle and cPickle modules use compatible data formats, so they may be used interchangeably.
而 當(dāng)你翻看(或點(diǎn)擊)Python手冊(cè)時(shí),請(qǐng)一定也要看看cPickle模塊的條目,它是pickle的C語(yǔ)言實(shí)現(xiàn),性能上更快。您可以顯式導(dǎo)入 cPickle替代pickle,以大幅提升速度;其主要的限制是,你不能繼承該版本的Pickle和Unpickle,因?yàn)樗鼈兪呛瘮?shù),而不是類(多數(shù) 程序并不要求它們是類)。pickle和cPickle模塊使用兼容的數(shù)據(jù)格式,所以它們可以互換使用。
If it is available in your Python, the shelve module automatically chooses the cPickle module for faster serialization, instead of pickle. I haven't explained shelve yet, but I will now.
Powered by: C++博客 Copyright © 金慶