我有一个脚本,另一个Python文件mappings.py
包含一堆dicts
和tuples-of-tuples
)。其中的每一个都在第0天填充了让我们对“名称”和“年龄”值对进行映射的基线。这些又被添加为参考电子表格的行。
在任何给定的一天,将从新的一天的电子表格中读取数据。如果任何记录已存在于映射字典或元组之一中,则数据将被写入适当的行。
这是挑战:在任何一天,如果输入电子表格中的某行在mappings.py
中尚无条目,我想:
提示用户为给定名称指定Age值
以某种方式将此Name:Age对添加到mappings.py中的相应字典或元组,以便在随后的日子中,如果脚本再次遇到该Name,它已经“知道”该名称。
所以问题是:如何在文件中而不是在内存中而是在实际文件本身中附加给定的数据结构?因此,如果有问题的字典称为mydict
,并且我要添加一个新的Name:Age对,则可以在内存中执行此操作:
mappings.py.mydict[$newName] = [$newAge]
但是,实际上我该如何使用这些新数据来更新文件以进行保存呢?最终用户不想直接打开
mappings.py
,因此我将显示一些弹出窗口来接收用户指定的配对。我想知道如何才能最好地节省这对货币。 最佳答案
使用泡菜(或Python 2中的cPickle,因为它比普通泡菜要快得多)的常用方法是:
从pickle文件中解开数据结构
更新程序中的数据结构
腌制更新的结构,覆盖原始的腌制文件,可能会保存该原始文件的备份。
腌制过程相当快,因此,除非您要腌制数以百万计的(名称,年龄)对,否则该策略就足够了。
将数据附加到pickle文件中的单个项目是不切实际的。如果您使用人类可读的pickle协议版本0,则可以在pickle文件中附加项目,但这很麻烦,手动修改pickle文件的内容不是一个好策略。
但是,将新的数据结构附加到现有的pickle文件中很容易,只需解开文件中的文件即可适当地处理数据。
下面的代码从泡菜文件中读取一系列字典,将它们全部合并为一个字典。然后,它创建一个新的字典并将其附加到现有的pickle文件中。
#!/usr/bin/env python
''' Appending data to a pickle file
See http://stackoverflow.com/q/31365239/4014959
Written by PM 2Ring 2015.07.12
'''
import cPickle as pickle
from random import choice, randint
from string import ascii_lowercase
#Create a random lowercase string
def rand_str(strlen=5):
return ''.join([choice(ascii_lowercase) for _ in xrange(strlen)])
#Name of pickle file
fname = 'pickletest.pkl'
#Attempt to read the dicts from the pickle file
all_data = {}
count = 0
try:
with open(fname, 'rb') as fh:
while True:
d = pickle.load(fh)
count += 1
print 'Record %2d: %s' % (count, d)
all_data.update(d)
except EOFError:
pass
except IOError as e:
print '%s; the file will be created.' % e
print '\nCurrent data\n%s' % all_data
#Create a new record
d = dict((rand_str(), randint(10, 99)) for _ in xrange(5))
print '\nNew data\n%s' % d
#Append the record to the pickle file, using protocol 2
with open(fname, 'ab') as fh:
pickle.dump(d, fh, 2)
这是该程序运行3次的一些典型输出。
[Errno 2] No such file or directory: 'pickletest.pkl'; the file will be created.
Current data
{}
New data
{'veria': 65, 'glsjp': 69, 'zvvho': 11, 'ejqnt': 36, 'gmpaq': 54}
#----------------------------------------------------------------
Record 1: {'veria': 65, 'glsjp': 69, 'zvvho': 11, 'ejqnt': 36, 'gmpaq': 54}
Current data
{'veria': 65, 'glsjp': 69, 'zvvho': 11, 'ejqnt': 36, 'gmpaq': 54}
New data
{'dptdp': 31, 'waydc': 81, 'zejbe': 34, 'fimgy': 51, 'sdwnp': 90}
#----------------------------------------------------------------
Record 1: {'veria': 65, 'glsjp': 69, 'zvvho': 11, 'ejqnt': 36, 'gmpaq': 54}
Record 2: {'dptdp': 31, 'sdwnp': 90, 'zejbe': 34, 'fimgy': 51, 'waydc': 81}
Current data
{'fimgy': 51, 'zejbe': 34, 'ejqnt': 36, 'gmpaq': 54, 'veria': 65, 'glsjp': 69, 'waydc': 81, 'dptdp': 31, 'zvvho': 11, 'sdwnp': 90}
New data
{'cavsw': 84, 'unokw': 14, 'irqfh': 60, 'avddt': 50, 'pszdk': 40}
在您的问题中,您提到需要保存一些元组的字典和元组。可以改编我的代码来解决这个问题,但是如果您有很多单独的字典和元组,则可能会变得凌乱。
将那些元组的元组转换为字典可能是值得的,因为搜索
dict
比元组或列表要快得多。还可以考虑结合您的命令。如果不宜将所有内容都放到一个简单的字典中,请考虑使用一个字典列表或一个字典。