用 pickle 转储数据

Dumping data with pickle

我对如何使用感到非常困惑 pickle,我试图通过存储已计算的值并为计算的值创建 pickle 文件来加快计算速度。当尚未计算某个函数时,我想打开 pickle 文件并创建新计算函数的新输入。这是我的尝试:

try:
    with open('EinsteinBbb.pickle','rb') as f:
        Bbb = pickle.load(f)
except:
    Bbb = dict()
def EinsteinBbb(nl, ll, nu, lu):

    global Bbb
    try:
        Bbbfile=pickle.load(open('EinsteinBbb.pickle','rb'))
    # Check if Bbb[(nl, ll, nu, lu)] needs to be computed
        if True: #TODO: replace with the correct condition
            print('Computing Bbb[{0}, {1}, {2}, {3}]'.format(nl, ll, nu, lu))
    except:   
        Bbb[(nl, ll, nu, lu)] = nl*ll*nu*lu
        with open('EinsteinBbb.pickle','wb') as f:
            pickle.dump(Bbb, f)
        with open('EinsteinBbb.pickle','rb') as f:
            EinsteinBbb_read = pickle.load(f)
        # TODO: Open 'EinsteinBbb.pickle' with write mode and dump Bbb so that it does not need to be recomputed
    return Bbb[(nl, ll, nu, lu)]
print(EinsteinBbb(1,2,3,4))

当我尝试 print(EinsteinBbb(2,1,2,0)) 我得到 TypeError: string indices must be integers 我觉得我的代码远非正确,但任何建议都会非常有帮助!

编辑: 创建一个最小的可复制文件使 TypeError 消失,我认为这与代码的存储位置有关,但现在我得到 KeyError 除了我第一次 运行 代码以外的任何键。

我认为以下内容可以满足您的需求(包括您所有的 TODO 以及不为 Bbb 字典中不存在的键生成 KeyError)。它使用异常来确定何时可以从现有的腌制缓存文件初始化字典,以及何时尝试访问 non-existent 条目以便为它添加新条目。

我输入了打印调用的数量,以使您能够看到它在做什么。

提示:大多数时候你应该避免在处理异常时使用“裸”except:语句,因为它们可以隐藏你 可能喜欢允许出现,如 SyntaxErrors 或 SIGINT 键盘 (Ctrl + C) 信号,因此不希望被抑制。在您不确定会发生什么的情况下,请改用 except Exception: 以避免捕获过多的问题(因为它不会包含它们)。

import pickle


PICKLE_FILEPATH = 'EinsteinBbb.pickle'

# Load or create cache dictionary
try:
    with open(PICKLE_FILEPATH, 'rb') as f:
        Bbb = pickle.load(f)
    print('Bbb dictionary read from file.')
except Exception:
    print('Creating Bbb dictionary.')
    Bbb = dict()

def EinsteinBbb(nl, ll, nu, lu):
    try:
        return_value = Bbb[(nl, ll, nu, lu)]
        print(f'Using existing entry for ({nl}, {ll}, {nu}, {lu}) in Bbb.')
    except KeyError:
        print(f'Adding entry ({nl}, {ll}, {nu}, {lu}) to Bbb.')
        return_value = Bbb[(nl, ll, nu, lu)] = nl*ll*nu*lu
        # Overwrite pickle file with updated dictionary.
        with open(PICKLE_FILEPATH, 'wb') as f:
            pickle.dump(Bbb, f)

    return return_value

print(f'{EinsteinBbb(1,2,3,4)=}')
#print(f'{EinsteinBbb(2,3,4,5)=}')