尝试附加JSON文件的Python错误

时间:2018-07-07 18:32:31

标签: python json

我是Python的新手,所以我的问题可能很容易解决,但是经过数天的尝试和搜索互联网之后,我找不到任何东西。

因此,我构建了一个脚本来从Twitter流数据并将收集的数据存储到json文件中,以便以后可以访问它并执行任何操作。该脚本从一个单独的文件中提取consumer keytokenaccess info之类的用户凭据以进行身份​​验证(我相信有一种更好,更安全的方法可以做到这一点,只是目前的概念证明)使用此代码:

with open('Twitter_Credentials.json', mode = 'a+') as tc:
            data = json.load(tc)
            if user not in data['names']:
                user_dict = dict()
                user_dict[user] = {'key':'','secret':'','token':'','token_secret':''}
                user_dict[user]['key'] = input('Twitter Consumer Key: ')
                user_dict[user]['secret'] = input('Twitter Consumer Secret: ')
                user_dict[user]['token'] = input('Twitter Access Token: ')
                user_dict[user]['token_secret'] = input('Twitter Access Secret: ')
                data['names'].append(user_dict)
                json.dump(data,tc, indent = 2, ensure_ascii = False)
                tc.close()

我遇到的问题是,如果我想将另一个用户及其凭据附加到此文件中,我将继续收到此错误:

File "(filepath)", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

我已经尝试过的东西:

  • 使用'r''r+''w''w+'修改模式
  • load()dump()更改为loads()dumps()
  • 更改编码

使用'r+''w+'并没有给我一个错误,但是它确实复制了原始用户,因此它们出现了多次。我想消除它,以便在添加时不会重复。任何见识将不胜感激。预先感谢。

1 个答案:

答案 0 :(得分:3)

JSON文件是包含单个JSON文档的文件。如果您向其附加另一个JSON字符串,则它不再是JSON文件。

the docs说:

  

注意与picklemarshal不同,JSON不是框架协议,因此请尝试使用相同的 fp 重复调用dump()来序列化多个对象将导致无效的JSON文件。


如果您实际上不是尝试将多个文档存储在一个文件中,那么修复很容易:您要做的是打开文件,加载文件,修改数据,然后打开文件。再次归档并覆盖它。像这样:

with open('Twitter_Credentials.json', mode = 'r') as tc:
    data = json.load(tc)
if user not in data['names']:
    # blah blah
    with open('Twitter_Credentials.json', mode = 'w') as tc:
        json.dump(data, tc, indent = 2, ensure_ascii = False)

请注意,我使用的是w模式,而不是a,因为我们想用新文件覆盖旧文件,而不是在文件末尾添加内容。


如果您正在尝试存储多个文档,则无法使用JSON进行存储。幸运的是,有一些基于JSON的非常简单的框架协议(JSONlines,NDJ等)被普遍使用。这样的格式有3种或4种,但有细微的差别,但所有这些的关键在于每个JSON文档本身都是一行,并且文档之间有换行符。

但是使用ensure_ascii=False意味着您没有在字符串中转义换行符,而indent=2意味着您在文档中的字段之间添加了更多换行符,那么您什么也不做来写每个文档后的换行符。因此,您的输出不再是有效的JSONlines,而是有效的JSONlines。

此外,即使您已解决所有问题,也要执行一个json.load,它将仅读取JSONlines文件中的第一个文档,然后对同一文件执行json.dump,该文档将在该文档之后编写第二个文档,覆盖其中的所有内容。例如,您很容易最终覆盖上一个第二文档的一半,而将另一半作为垃圾留待以后阅读。因此,您需要重新考虑您的逻辑。至少,您要执行与上述相同的操作,两次打开文件:

with open('Twitter_Credentials.json', mode = 'r') as tc:
    data = json.load(tc)
if user not in data['names']:
    # blah blah
    with open('Twitter_Credentials.json', mode = 'a') as tc:
        json.dump(data, tc)
        tc.write('\n')

这次我正在使用a模式,因为这次我们要做要在现有文件的末尾添加新行。