我对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()
并修改编码代码<>F221
使用'r+'
和'w+'
没有给我一个错误,但它确实复制了原始用户,所以它们出现了多次。我想要消除它,这样当它追加时,它就不会重复。任何见解都将不胜感激。提前谢谢。
发布于 2018-07-08 02:47:03
JSON文件是包含单个JSON文档的文件。如果向其追加另一个JSON字符串,则它不再是JSON文件。
正如the docs所说:
JSON注意:与pickle
和marshal
不同,
不是一种框架协议,因此尝试使用相同的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的框架协议--JSONline、NDJ等--这些都是常用的。有三到四种不同的这样的格式,但都有细微的差异,但所有这些格式的关键是每个JSON文档都在一行中,文档之间有换行符。
但是使用ensure_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
模式,因为这一次我们确实想要在现有文件的末尾添加一个新行。
https://stackoverflow.com/questions/51225954
复制相似问题