【问题标题】:Error in writing Python dictionary to a file将 Python 字典写入文件时出错
【发布时间】:2015-06-30 17:48:01
【问题描述】:

这是我的代码的简化版本:

test={}
for i in range(10):
   for j in range(15):
     test[i,j]=i*j
with open('boo.json', 'w') as f:
    json.dump(test, f)

我收到以下错误:

raise TypeError("key " + repr(key) + " 不是字符串")

有什么办法吗?

【问题讨论】:

  • JSON 键必须是字符串。为您的键找到一个字符串表示形式。

标签: python json python-3.x dictionary


【解决方案1】:

JSON 格式要求对象键是字符串;您不能使用数字元组作为键。

您必须找到一种使用字符串的表示,而不是为您的数据建模得足够好。您可以使用嵌套字典并将数字转换为字符串,例如:

test = {}
for i in range(10):
    nested = test[str(i)] = {}
    for j in range(15):
        nested[str(j)] = i * j

with open('boo.json', 'w') as f:
    json.dump(test, f)

如果你必须只有一个级别,你必须生成一个包含两个整数的字符串;你可以创建一个逗号分隔的键:

test['{},{}'.format(i, j)] = i * j

或使用任何其他分隔符;当然,您必须教 JSON 使用者期望解析这些键。

请注意,对于您的演示数据结构,仅使用列表(JSON 数组)会容易得多;毕竟这些都可以用数字来寻址:

test = []
for i in range(10):
    nested = []
    for j in range(15):
        nested.append(i * j)

或使用列表推导:

test = [[i * j for j in range(15)] for i in range(10)]

演示:

>>> import json
>>> test = {}
>>> for i in range(10):
...     nested = test[str(i)] = {}
...     for j in range(15):
...         nested[str(j)] = i * j
... 
>>> print json.dumps(test, sort_keys=True, indent=4, separators=(',', ': '))
{
    "0": {
        "0": 0,
        "1": 0,
        "10": 0,
        "11": 0,
        "12": 0,
        "13": 0,
        "14": 0,
        "2": 0,
        "3": 0,
        "4": 0,
        "5": 0,
        "6": 0,
        "7": 0,
        "8": 0,
        "9": 0
    },
    "1": {
        "0": 0,
        "1": 1,
        "10": 10,
        "11": 11,
        "12": 12,
        "13": 13,
        "14": 14,
        "2": 2,
        "3": 3,
        "4": 4,
        "5": 5,
        "6": 6,
        "7": 7,
        "8": 8,
        "9": 9
    },
    "2": {
        "0": 0,
        "1": 2,
        "10": 20,
        "11": 22,
        "12": 24,
        "13": 26,
        "14": 28,
        "2": 4,
        "3": 6,
        "4": 8,
        "5": 10,
        "6": 12,
        "7": 14,
        "8": 16,
        "9": 18
    },
    "3": {
        "0": 0,
        "1": 3,
        "10": 30,
        "11": 33,
        "12": 36,
        "13": 39,
        "14": 42,
        "2": 6,
        "3": 9,
        "4": 12,
        "5": 15,
        "6": 18,
        "7": 21,
        "8": 24,
        "9": 27
    },
    "4": {
        "0": 0,
        "1": 4,
        "10": 40,
        "11": 44,
        "12": 48,
        "13": 52,
        "14": 56,
        "2": 8,
        "3": 12,
        "4": 16,
        "5": 20,
        "6": 24,
        "7": 28,
        "8": 32,
        "9": 36
    },
    "5": {
        "0": 0,
        "1": 5,
        "10": 50,
        "11": 55,
        "12": 60,
        "13": 65,
        "14": 70,
        "2": 10,
        "3": 15,
        "4": 20,
        "5": 25,
        "6": 30,
        "7": 35,
        "8": 40,
        "9": 45
    },
    "6": {
        "0": 0,
        "1": 6,
        "10": 60,
        "11": 66,
        "12": 72,
        "13": 78,
        "14": 84,
        "2": 12,
        "3": 18,
        "4": 24,
        "5": 30,
        "6": 36,
        "7": 42,
        "8": 48,
        "9": 54
    },
    "7": {
        "0": 0,
        "1": 7,
        "10": 70,
        "11": 77,
        "12": 84,
        "13": 91,
        "14": 98,
        "2": 14,
        "3": 21,
        "4": 28,
        "5": 35,
        "6": 42,
        "7": 49,
        "8": 56,
        "9": 63
    },
    "8": {
        "0": 0,
        "1": 8,
        "10": 80,
        "11": 88,
        "12": 96,
        "13": 104,
        "14": 112,
        "2": 16,
        "3": 24,
        "4": 32,
        "5": 40,
        "6": 48,
        "7": 56,
        "8": 64,
        "9": 72
    },
    "9": {
        "0": 0,
        "1": 9,
        "10": 90,
        "11": 99,
        "12": 108,
        "13": 117,
        "14": 126,
        "2": 18,
        "3": 27,
        "4": 36,
        "5": 45,
        "6": 54,
        "7": 63,
        "8": 72,
        "9": 81
    }
}

或制作扁平结构:

>>> test = {}
>>> for i in range(10):
...     for j in range(15):
...         test['{},{}'.format(i, j)] = i * j
... 
>>> print json.dumps(test, sort_keys=True, indent=4, separators=(',', ': '))
{
    "0,0": 0,
    "0,1": 0,
    "0,10": 0,
    "0,11": 0,
    "0,12": 0,
    "0,13": 0,
    "0,14": 0,
    "0,2": 0,
    "0,3": 0,
    "0,4": 0,
    "0,5": 0,
    "0,6": 0,
    "0,7": 0,
    "0,8": 0,
    "0,9": 0,
    "1,0": 0,
    "1,1": 1,
    "1,10": 10,
    "1,11": 11,
    "1,12": 12,
    "1,13": 13,
    "1,14": 14,
    "1,2": 2,
    "1,3": 3,
    "1,4": 4,
    "1,5": 5,
    "1,6": 6,
    "1,7": 7,
    "1,8": 8,
    "1,9": 9,
    "2,0": 0,
    "2,1": 2,
    "2,10": 20,
    "2,11": 22,
    "2,12": 24,
    "2,13": 26,
    "2,14": 28,
    "2,2": 4,
    "2,3": 6,
    "2,4": 8,
    "2,5": 10,
    "2,6": 12,
    "2,7": 14,
    "2,8": 16,
    "2,9": 18,
    "3,0": 0,
    "3,1": 3,
    "3,10": 30,
    "3,11": 33,
    "3,12": 36,
    "3,13": 39,
    "3,14": 42,
    "3,2": 6,
    "3,3": 9,
    "3,4": 12,
    "3,5": 15,
    "3,6": 18,
    "3,7": 21,
    "3,8": 24,
    "3,9": 27,
    "4,0": 0,
    "4,1": 4,
    "4,10": 40,
    "4,11": 44,
    "4,12": 48,
    "4,13": 52,
    "4,14": 56,
    "4,2": 8,
    "4,3": 12,
    "4,4": 16,
    "4,5": 20,
    "4,6": 24,
    "4,7": 28,
    "4,8": 32,
    "4,9": 36,
    "5,0": 0,
    "5,1": 5,
    "5,10": 50,
    "5,11": 55,
    "5,12": 60,
    "5,13": 65,
    "5,14": 70,
    "5,2": 10,
    "5,3": 15,
    "5,4": 20,
    "5,5": 25,
    "5,6": 30,
    "5,7": 35,
    "5,8": 40,
    "5,9": 45,
    "6,0": 0,
    "6,1": 6,
    "6,10": 60,
    "6,11": 66,
    "6,12": 72,
    "6,13": 78,
    "6,14": 84,
    "6,2": 12,
    "6,3": 18,
    "6,4": 24,
    "6,5": 30,
    "6,6": 36,
    "6,7": 42,
    "6,8": 48,
    "6,9": 54,
    "7,0": 0,
    "7,1": 7,
    "7,10": 70,
    "7,11": 77,
    "7,12": 84,
    "7,13": 91,
    "7,14": 98,
    "7,2": 14,
    "7,3": 21,
    "7,4": 28,
    "7,5": 35,
    "7,6": 42,
    "7,7": 49,
    "7,8": 56,
    "7,9": 63,
    "8,0": 0,
    "8,1": 8,
    "8,10": 80,
    "8,11": 88,
    "8,12": 96,
    "8,13": 104,
    "8,14": 112,
    "8,2": 16,
    "8,3": 24,
    "8,4": 32,
    "8,5": 40,
    "8,6": 48,
    "8,7": 56,
    "8,8": 64,
    "8,9": 72,
    "9,0": 0,
    "9,1": 9,
    "9,10": 90,
    "9,11": 99,
    "9,12": 108,
    "9,13": 117,
    "9,14": 126,
    "9,2": 18,
    "9,3": 27,
    "9,4": 36,
    "9,5": 45,
    "9,6": 54,
    "9,7": 63,
    "9,8": 72,
    "9,9": 81
}

【讨论】:

  • 谢谢;我的代码是我实际拥有的非常简化的版本。我确实需要使用字典。字典的key格式为[i,j,k,l,m];我使用函数为字典赋值;将它们写入文件,然后从文件中读取它们。使用这种方法不会使从文件中读回它变得更加困难吗?为此目的使用文本文件而不是 JSON 更好吗?
  • @NNsr:JSON 不是这种结构的最佳格式。您可以改用pickle module
  • 只是一个澄清问题:我使用 JSON 只是因为我觉得它比 pickle 快得多。我正在使用的字典是一本包含 1500 万个元素的大型字典。泡菜是个好选择吗?我知道这是对主要问题的偏离;但是,IO 认为不值得为此提出一个新问题。
  • @NNsr:为什么不对其进行基准测试? JSON 是一种非常受限制的格式。 pickle 在 Python 2 中有一个 cPickle 优化版本(它是 Python 3 中的标准实现)。
【解决方案2】:

你需要你的 json 对象键是字符串。

尝试这样做:

#!/usr/bin/env python3
import json

test={}
for i in range(10):
   for j in range(15):
     test["%s,%s" %(i,j)]=i*j
with open('boo.json', 'w') as f:
    json.dump(test, f)

这会将 i 和 j 的值放入字符串格式(中间有逗号),因此您的键将是一个字符串。

@Martijn 在他的回答中做得更好。

【讨论】:

  • 不,json.dump() 将 Python 结构转换为字符串。
  • 是的...我后来意识到错误..上面的代码有效。
  • 是的,您找到了另一种将键转换为字符串的方法。您没有解释为什么会这样,也没有更正答案的第一句话..
  • 你是对的。对不起,我是一个新的贡献者,所以还在研究如何最好地提供帮助。感谢您让我走上正确的道路。根据您的建议更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2020-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-01
  • 2014-04-04
  • 1970-01-01
相关资源
最近更新 更多