<p>您可以使用标准库中的<code>pickle</code>模块。
下面是它在示例中的一个基本应用:</p>
<pre><code>import pickle
class Company(object):
def __init__(self, name, value):
self.name = name
self.value = value
with open('company_data.pkl', 'wb') as output:
company1 = Company('banana', 40)
pickle.dump(company1, output, pickle.HIGHEST_PROTOCOL)
company2 = Company('spam', 42)
pickle.dump(company2, output, pickle.HIGHEST_PROTOCOL)
del company1
del company2
with open('company_data.pkl', 'rb') as input:
company1 = pickle.load(input)
print(company1.name) # -> banana
print(company1.value) # -> 40
company2 = pickle.load(input)
print(company2.name) # -> spam
print(company2.value) # -> 42
</code></pre>
<p>您还可以定义自己的简单实用程序,如下所示,它打开一个文件并向其中写入一个对象:</p>
<pre><code>def save_object(obj, filename):
with open(filename, 'wb') as output: # Overwrites any existing file.
pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
# sample usage
save_object(company1, 'company1.pkl')
</code></pre>
<h2>更新</h2>
<p>由于这是一个非常流行的答案,我想谈谈一些稍微高级的使用主题。</p>
<h3><code>cPickle</code>(或<code>_pickle</code>)与<code>pickle</code></h3>
<p>实际上最好使用<a href="http://docs.python.org/2/library/pickle.html#module-cPickle" rel="nofollow noreferrer">^{<cd2>}</a>模块,而不是<code>pickle</code>,因为前者是用C编写的,而且速度更快。它们之间有一些细微的差别,但是在大多数情况下它们是等价的,C版本将提供非常优异的性能。切换到它并不容易,只需将<code>import</code>语句更改为:</p>
<pre><code>import cPickle as pickle
</code></pre>
<p>在Python 3中,<code>cPickle</code>被重命名为<code>_pickle</code>,但由于<code>pickle</code>模块现在自动看到<a href="https://stackoverflow.com/questions/19191859/what-difference-between-pickle-and-pickle-in-python-3">What difference between pickle and _pickle in python 3?</a>,因此不再需要这样做。</p>
<p>简而言之,您可以使用如下方法来确保代码在Python 2和3中都可用时始终使用C版本:</p>
<pre><code>try:
import cPickle as pickle
except ModuleNotFoundError:
import pickle
</code></pre>
<h3>数据流格式(协议)</h3>
<p><code>pickle</code>可以读写几种不同的、特定于Python的格式的文件,如<a href="https://docs.python.org/3/library/pickle.html#data-stream-format" rel="nofollow noreferrer">documentation</a>“Protocol version 0”中所述,称为<em>protocols</em>,因此是“人类可读的”。版本>;1是二进制的,可用的最高版本取决于所使用的Python版本。默认值也取决于Python版本。在Python 2中,默认的是协议版本<code>0</code>,但在Python 3.8.1中,默认的是协议版本<code>4</code>。在Python3.x中,模块中添加了一个<code>pickle.DEFAULT_PROTOCOL</code>,但Python2中不存在。</p>
<p>幸运的是,在每个调用中都有写<code>pickle.HIGHEST_PROTOCOL</code>的速记法(假设这是您想要的,而且您通常会这样做),只需使用文本号<code>-1</code>-类似于通过负索引引用序列的最后一个元素。
所以,不要写:</p>
<pre><code>pickle.dump(obj, output, pickle.HIGHEST_PROTOCOL)
</code></pre>
<p>你可以写:</p>
<pre><code>pickle.dump(obj, output, -1)
</code></pre>
<p>无论哪种方式,如果创建了用于多个pickle操作的<code>Pickler</code>对象,则只需指定一次协议:</p>
<pre><code>pickler = pickle.Pickler(output, -1)
pickler.dump(obj1)
pickler.dump(obj2)
etc...
</code></pre>
<p><em>注意</em>:如果您所处的环境运行的是不同版本的Python,那么您可能需要显式地使用(即硬代码)一个特定的协议号,所有这些协议号都可以读取(较新版本通常可以读取较早版本生成的文件)。</p>
<h3>多个对象</h3>
<p>尽管pickle文件<em>可以包含任意数量的pickle对象,如上面的示例所示,但当它们的数量未知时,通常更容易将它们存储在某种大小可变的容器中,如<code>list</code>、<code>tuple</code>或<code>dict</code>,并在一次调用中将它们全部写入文件:</p>
<pre><code>tech_companies = [
Company('Apple', 114.18), Company('Google', 908.60), Company('Microsoft', 69.18)
]
save_object(tech_companies, 'tech_companies.pkl')
</code></pre>
<p>稍后使用以下命令恢复列表和其中的所有内容:</p>
<pre><code>with open('tech_companies.pkl', 'rb') as input:
tech_companies = pickle.load(input)
</code></pre>
<p>主要优点是不需要知道保存了多少对象实例,以便以后加载它们(尽管这样做时不需要这些信息<em>是</em>可能的,但需要一些稍微特殊的代码)。请参阅相关问题<a href="https://stackoverflow.com/questions/20716812/saving-and-loading-multiple-objects-in-pickle-file">Saving and loading multiple objects in pickle file?</a>的答案,以了解执行此操作的不同方法的详细信息。我个人喜欢@Lutz Prechelt的<a href="https://stackoverflow.com/a/28745948/355230">answer</a>最好的。下面是它改编的例子:</p>
<pre><code>class Company:
def __init__(self, name, value):
self.name = name
self.value = value
def pickled_items(filename):
""" Unpickle a file of pickled data. """
with open(filename, "rb") as f:
while True:
try:
yield pickle.load(f)
except EOFError:
break
print('Companies in pickle file:')
for company in pickled_items('company_data.pkl'):
print(' name: {}, value: {}'.format(company.name, company.value))
</code></pre>