如何根据用户输入更新和保存 python 脚本(仅变量,无逻辑)?

How to update and save a python script (variables only, no logic) based on user input?

我有一个脚本,还有另一个 Python 文件 mappings.py,其中包含一堆 dictstuples-of-tuples)。其中每一个都在第 0 天填充了 Name 和 Age 值对映射的基线。这些又被添加为参考电子表格的行。

在任何给定的一天,将从新一天的电子表格中读取数据。如果任何记录已经在映射字典或元组之一中,则数据将写入相应的行。

挑战如下:在任何给定的一天,如果输入电子表格中的一行 mappings.py 中还没有条目 ,我想:

所以问题是:我如何追加到文件中的给定数据结构,而不是在内存中,而是在实际文件本身中?因此,如果有问题的字典称为 mydict,并且我要添加一个新的 Name:Age 对,我可以在内存中做:

mappings.py.mydict[$newName] = [$newAge]

但是我如何实际更新文件,以便使用这个新数据进行保存?最终用户不想直接打开 mappings.py,因此我将显示一些弹出窗口以接收用户指定的对。然后我想知道如何最好地保存这对。

如果 mappings.py 不需要用户可读,请使用常规字典并将 -load\save 作为 pickle(参见相关问题)

使用 pickle(或 Python 2 中的 cPickle,因为它比普通 pickle 快得多)的常用方法是

  1. 从 pickle 文件中解开你的数据结构
  2. 更新程序中的数据结构
  3. pickle 更新后的结构,覆盖原始 pickle 文件,可能会保存该原始文件的备份。

酸洗过程相当快,因此除非您要酸洗数百万对(姓名、年龄),否则该策略应该足够了。

将数据附加到 pickle 文件中的单个项目是不切实际的。如果您使用人类可读的 pickle 协议版本 0,可以在 pickle 文件中追加项目,但它很混乱,并且手动修改 pickle 文件的内容是 好策略。

但是,将新的数据结构附加到现有的 pickle 文件非常容易,您只需要在取消 pickle 文件时适当地处理数据即可。

下面的代码从 pickle 文件中读取一系列字典,将它们全部合并成一个字典。然后它创建一个新的字典并将其附加到现有的 pickle 文件中。

#!/usr/bin/env python

''' Appending data to a pickle file

    See 

    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 比搜索元组或列表快 。还可以考虑组合你的字典。如果将所有内容都放入一个单一的扁平字典中是不合适的,请考虑使用字典列表或字典字典。

如果你想存储一个可以动态更新的字典、列表、字符串和数字的结构,你似乎在描述一个面向文档的数据库,比如mongodb。虽然,如果您可以选择只加载一个普通文件,更改您需要的内容并覆盖它,那么这会简单得多。

就我个人而言,我会选择 json 而不是 pickle,因为您只提到了 json 可序列化的类型。优点包括文件可被人类和其他(非Python)软件读取,以及 Pickle 版本的兼容性没有问题。缺点是你不能存储例如函数或 class.