如何临时保存Python中的数据?

How to temporary save data in Python?

我从字典中的 GPS 传感器读取位置数据,并以循环间隔将其发送到服务器。

如果我没有覆盖,数据将保存在一个列表中。 如果可以重新建立连接,将传输所有列表项。

但是如果发生断电,所有临时数据元素都将丢失。

什么是最好的 pythonic 解决方案来保存这些数据? 我正在使用 SD 卡作为存储,所以我不确定将每个元素写入文件是否是最好的解决方案。

当前实施:

stageddata = []
position = {'lat':'1.2345', 'lon':'2.3455', 'timestamp':'2020-10-18T15:08:04'}
if not transmission(position):
   stageddata.append(position)
else:
   while stageddata:
     position = stageddata.pop()
     if not transmission(position):
        stageddata.append(position)
        return

编辑:寻找“最佳”解决方案可能非常主观。我同意 zvone,可以防止停电。也许关机例程应该保存临时数据。 所以问题可能是如何将给定列表保存到文件中?

Python 中临时存储的一个很好的解决方案是 tempfile

您可以使用它,例如,如下所示:

import tempfile

with tempfile.TemporaryFile() as fp:

     # Store your varibale
     fp.write(your_variable_to_temp_store)

     # Do some other stuff 

     # Read file
     fp.seek(0)
     fp.read()

也许将其保存为二进制代码有助于最大限度地减少存储空间。 'pickle' 和 'shelve' 模块将帮助存储对象和序列化(序列化对象意味着将其状态转换为字节流,以便字节流可以恢复为对象的副本),但你应该小心,当你解决电源中断时,它不会覆盖你一直存储的数据,使用 open(file, "a") (a== append),你可以避免这种情况。

同意zvone的评论。为了了解最佳解决方案,我们需要更多信息。

以下是一个可靠且可配置的解决方案。

import os
import pickle


backup_interval = 2
backup_file = 'gps_position_backup.bin'


def read_backup_data():
    file_backup_data = []
    if os.path.exists(backup_file):
        with open(backup_file, 'rb') as f:
            while True:
                try:
                    coordinates = pickle.load(f)
                except EOFError:
                    break
                file_backup_data += coordinates

    return file_backup_data


# When the script is started and backup data exists, stageddata uses it
stageddata = read_backup_data()


def write_backup_data():
    tmp_backup_file = 'tmp_' + backup_file
    with open(tmp_backup_file, 'wb') as f:
        pickle.dump(stageddata, f)
    os.replace(tmp_backup_file, backup_file)
    print('Wrote data backup!')


# Mockup variable and method
transmission_return = False
def transmission(position):
    return transmission_return


def try_transmission(position):
    if not transmission(position):
        stageddata.append(position)
        if len(stageddata) % backup_interval == 0:
            write_backup_data()
    else:
        while stageddata:
            position = stageddata.pop()
            if not transmission(position):
                stageddata.append(position)
                return
            else:
                if len(stageddata) % backup_interval == 0:
                    write_backup_data()


if __name__ == '__main__':
    # transmission_return is False, so write to backup_file
    for counter in range(10):
        position = {'lat':'1.2345', 'lon':'2.3455'}
        try_transmission(position)

    # transmission_return is True, transmit positions and "update" backup_file
    transmission_return = True
    position = {'lat':'1.2345', 'lon':'2.3455'}
    try_transmission(position)

我将你的代码移到了一些函数中。使用变量 backup_interval,可以控制备份写入磁盘的频率。

补充说明:

  • 我使用 built-in pickle module, since the data does not have to be human readable or transformable for other programming languages. Alternatives are JSON, which is human readable, or msgpack, which might be faster, but needs an extra package to be installed. The tempfile 不是 pythonic 解决方案,因为在程序崩溃的情况下无法轻易检索它。
  • stageddata 在到达 backup_interval 时写入磁盘(很明显),而且在 while 循环中传输 returns True 时也会写入磁盘。这是“同步”磁盘上数据所必需的。
  • 数据每次都是全新写入磁盘。一种更复杂的方法是只附加新添加的位置,但我之前描述的同步部分也会更复杂。此外,更安全的临时文件方法(请参阅下面的编辑)将不起作用。

编辑:我刚刚重新考虑了您的用例。这里的主要问题是:恢复数据,即使程序在任何时候被中断(由于电源中断或其他原因)。我的第一个解决方案只是将数据写入磁盘(这解决了部分问题),但仍有可能发生程序在写入磁盘时崩溃的情况。在那种情况下,文件可能会损坏并且数据会丢失。我修改了函数write_backup_data(),让它先写入临时文件,然后替换旧文件。所以现在,即使有很多数据要写入磁盘,当机发生在那里,之前的备份文件仍然可用。