【问题标题】:What's a good temporary storage & transport format for Python?Python 有什么好的临时存储和传输格式?
【发布时间】:2011-10-19 03:03:29
【问题描述】:

我正在用 Python 编写一个脚本,它将吐出一些组织为字典列表的数据:

[{'name': 'first_thing', 'color': 'blue', 'flavour': 'watermelon' },
 {'name': 'second_thing', 'color': 'red' },
 {'name': 'third_thing', 'color': 'blue', 'size': 'huge!' }]

我正在尝试决定一种将这些数据存储在文件中的方法。我的考虑:

  1. 我希望它易于阅读和编写,因此我可以将数据加载回脚本并进一步操作。
  2. 我希望它是一种非 python 特定的格式。也许以后我会想在 PHP 或其他东西中使用这些数据,谁知道呢?
  3. 我希望它是一种易于附加更多数据的格式。如果我的文件有一个包含 1000 个小 dict 项的列表,我不想将所有 1000 个项加载到内存中,只是为了在末尾再添加一个项。

我的第一次尝试是使用 Pickle,它符合简单的标准,但它依赖于 Python,我必须取消腌制、附加,然后重新腌制。

我认为其他似乎可行的格式(但我反对):

  • JSON(可能会很烦人)
  • 搁置(特定于 python)
  • CSV(类似于胶带,不那么优雅,但它可能会起作用)
  • 类似 sqlite 之类的轻量级数据库(这里可能太花哨了)

有人对这些或其他格式有任何论据吗?

【问题讨论】:

  • 你看过 XML 吗?您可以创建自己的模式并将其用作使用您输出的数据的所有程序的标准。虽然 XML 很大,但它非常适合跨语言/平台的东西。
  • 我没有考虑过 XML。这当然是一种跨平台的格式。有没有办法像 pickle.dump() 一样简单地编写它?
  • 我从未尝试过在 python 中编写 XML,但它肯定应该有一两个库,但是它不会像 pickle 那样简单,而且可能比 CSV 更繁琐一些,尝试wiki.python.org/moin/PythonXml 以获得良好的开端。
  • 刚刚想起这个问题...多年后,有了更多经验,我可能会建议自己使用jsonl(jsonlines.org)。

标签: python file-io storage


【解决方案1】:

泡菜应该可以正常工作。 直接存储字典(而不是在列表中)以使附加更容易:

>>> from pickle import dump, load
>>> f = open('stor.bin', 'w')
>>> dump(dict(a=1), f)
>>> dump(dict(b=2), f)
>>> dump(dict(c=3), f)
>>> f.close()

在后续会话中,将另一个 dump() 直接附加到文件末尾:

>>> f = open('store.bin', 'a')
>>> dump(dict(d=4), f)
>>> f.close()   

要读取,只需重复执行 load() 直到到达文件末尾:

>>> f = open('stor.bin', 'r')
>>> load(f)
{'a': 1}
>>> load(f)
{'b': 2}
>>> load(f)
{'c': 3}
>>> load(f)
{'d': 4}
>>> load(f)

Traceback (most recent call last):
   ...
EOFError

【讨论】:

  • 这正是我建议你用 JSON 做的事情。
  • 没必要暴躁。不同之处在于,正如文档所说:“与 pickle 和 marshal 不同,JSON 不是框架协议,因此尝试通过重复调用 dump() 来序列化更多对象,并且相同的 fp 将导致 JSON 文件无效。”
  • @benauthor,我记得引用但倒退了。我以为它说 marshal 不像 JSON 和 pickle 那样框定。我的错。从技术上讲,在我看来你可以用 JSON 来做到这一点,因为它是自定界的,但显然 api 不支持它。
【解决方案2】:

鉴于您稍后需要附加数据,YAML 可能是您正在寻找的格式。它被明确设计为支持附加的数据元素(例如日志文件),json 故意是该语言的适当子集,并且它具有一些有用的元标记,专为自定义类的强大跨语言序列化而设计。

【讨论】:

  • 啊。单独的文档可以组成一个流。跨平台。简单的。宾果游戏。
  • 除了单独的文档,我发现一个长文档是一个多行列表(每个条目以'-'开头)也可以很容易地附加到,只要每个条目的数据停留在一条线上,它有选项。
【解决方案3】:

对于大多数情况,我认为 JSON 应该是您最好的选择。

使用 simplejson 将您的 list 的 dict 转换为 JSON,这将非常简单:

import simplejson as json
my_list = [{'name': 'first_thing', 'color': 'blue', 'flavour': 'watermelon'}, {'name': 'second_thing','color': 'red' }, {'name': 'third_thing', 'color': 'blue', 'size': 'huge!'}]
output = json.dumps(my_list, ident=4)

结果 JSON 将是:

[
    {
        "color": "blue",
        "flavour": "watermelon",
        "name": "first_thing"
    },
    {
        "color": "red",
        "name": "second_thing"
    },
    {
        "color": "blue",
        "name": "third_thing",
        "size": "huge!"
    }
]

现在,这个 JSON 是一个完全有效的 JSON 字符串。

这是一个JSON array。所以我认为你不需要做一个黑客来删除“[”和“]”。由于您将 python 列表传递给 simplejson,因此您返回一个 JSON 列表。

【讨论】:

  • 是的,但是当我明天想在同一个文件中添加更多项目时......也许我很厚,但我不需要做一些非常原始的字符串操作,比如在文件并切断关闭]等等?否则新项目如何进入包含列表?
  • 将 json 解码为 python 列表,将元素添加到列表并再次编码。
  • 对,但这就是我要避免的。我还没有进行性能测试,但我觉得从文件加载 1000 个项目以添加数字 1001 并写回文件会比让我直接将数字 1001 写入文件末尾的解决方案要慢。
【解决方案4】:

从您的示例数据 sn-p 来看,您的数据确实看起来比更复杂的格式更适合表格格式。如果您的 dicts 的键是事先知道的,并且在每个条目中都使用过,我认为 CSV 是正确的选择。 Python 也有一个 csv 模块可以让这更容易。

【讨论】:

  • 我想我有点懒,不想跟踪所有的键......我的真实数据实际上比我的例子要混乱得多。并非不可克服,我可能最终会这样做,但仍然没有完全卖掉。
  • 到底有多混乱,以何种方式?您能否进一步充实您对数据的描述?
  • 会有 15 个左右字段的固定列表,任何给定的项目都会有两个或全部。
  • 另外,你的乐高铭牌真棒! (看了你的资料)我在想圣诞礼物......
  • 关于铭牌,谢谢! :) 至于您的数据,这听起来并不那么混乱......是否有任何可能某些经理类型可能想要访问这些数据?他们往往喜欢 Excel,而 .csv 可以用于该用例,而其他的则不行。
猜你喜欢
  • 2018-07-26
  • 1970-01-01
  • 2011-10-30
  • 1970-01-01
  • 2010-09-24
  • 1970-01-01
  • 2013-12-31
  • 2015-04-22
  • 1970-01-01
相关资源
最近更新 更多