我是Python的新手,所以我的问题可能很容易解决,但是经过数天的尝试和搜索互联网之后,我找不到任何东西。
因此,我构建了一个脚本来从Twitter流数据并将收集的数据存储到json
文件中,以便以后可以访问它并执行任何操作。该脚本从一个单独的文件中提取consumer key
,token
和access 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+'
并没有给我一个错误,但是它确实复制了原始用户,因此它们出现了多次。我想消除它,以便在添加时不会重复。任何见识将不胜感激。预先感谢。
答案 0 :(得分:3)
JSON文件是包含单个JSON文档的文件。如果您向其附加另一个JSON字符串,则它不再是JSON文件。
the docs说:
注意与
pickle
和marshal
不同,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
模式,因为这次我们要做要在现有文件的末尾添加新行。