1

我对 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+'and'w+'并没有给我一个错误,但它确实复制了原始用户,因此他们出现了多次。我想消除它,以便在它附加时不会重复。任何见解将不胜感激。提前致谢。

4

1 回答 1

3

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

正如文档所说:

注意 与pickleand不同marshal,JSON 不是框架协议,因此尝试dump()使用相同fp重复调用序列化多个对象将导致 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)

请注意,我使用的是wmode,而不是a,因为我们想用新文件覆盖旧文件,而不是在它的末尾添加东西。


如果您尝试存储多个文档,那么您无法使用 JSON 来执行此操作。幸运的是,有一些非常简单的基于 JSON 的框架协议——JSONlines、NDJ 等——是常用的。有三到四种不同的格式,它们之间有细微的差别,但所有这些格式的关键是每个 JSON 文档都单独一行,文档之间有换行符。

但是 usingensure_ascii=False意味着您没有转义字符串中的换行符,并且indent=2意味着您在文档中的字段之间添加了更多换行符,然后您没有做任何事情来在每个文档之后写一个换行符。因此,您的输出不是有效的 JSONlines,而是有效的 JSON。

此外,即使您解决了所有这些问题,您也只是在做一个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模式,因为这次我们确实想在现有文件的末尾添加一个新行。

于 2018-07-07T18:47:03.413 回答