首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >尝试追加JSON文件时出现Python错误

尝试追加JSON文件时出现Python错误
EN

Stack Overflow用户
提问于 2018-07-08 02:32:31
回答 1查看 670关注 0票数 1

我对Python比较陌生,所以我的问题可能很容易解决,但在互联网上尝试和搜索了几天后,我什么也找不到。

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

代码语言:javascript
复制
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()

我遇到的问题是,如果我想将另一个用户和他们的凭据附加到这个文件中,我会一直收到这个错误:

代码语言:javascript
复制
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+'
  • Changing load()dump()将模式修改为loads()并修改编码代码<

>F221

使用'r+''w+'没有给我一个错误,但它确实复制了原始用户,所以它们出现了多次。我想要消除它,这样当它追加时,它就不会重复。任何见解都将不胜感激。提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2018-07-08 02:47:03

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

正如the docs所说:

JSON注意:与picklemarshal不同,

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

如果您实际上没有尝试在一个文件中存储多个文档,那么修复方法很简单:您要做的是打开文件,加载它,修改数据,然后再次打开文件并覆盖它。如下所示:

代码语言:javascript
复制
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的框架协议--JSONline、NDJ等--这些都是常用的。有三到四种不同的这样的格式,但都有细微的差异,但所有这些格式的关键是每个JSON文档都在一行中,文档之间有换行符。

但是使用ensure_ascii=False意味着您不会转义字符串中的换行符,而使用indent=2意味着您将在文档内的字段之间添加更多换行符,这样您就不需要在每个文档之后编写换行符了。因此,您的输出既不是有效的JSONlines,也不是有效的JSON。

而且,即使您解决了所有这些问题,您也是在执行单个json.load,它只从JSONlines文件中读取第一个文档,然后对同一文件执行json.dump,这将在第二个文档之后写入第二个文档,覆盖那里的任何内容。比方说,你可以很容易地覆盖之前第二个文档的一半,留下另一半作为垃圾留下来供以后阅读。所以,你需要重新考虑你的逻辑。至少,您需要执行与上述相同的操作,即打开文件两次:

代码语言:javascript
复制
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模式,因为这一次我们确实想要在现有文件的末尾添加一个新行。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51225954

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档