Python&;JSON:ValueError:Unterminated字符串起始于:
我已经阅读了多篇关于这一点的StackOverflow文章,以及谷歌前十大搜索结果中的大部分。我的问题不同之处在于,我使用python中的一个脚本来创建JSON文件。下一个脚本在10分钟后运行,无法读取该文件 简短版本,我为我的在线业务生成潜在客户。为了更好地分析这些潜在客户,我正在尝试学习python。我正在搜寻2年的潜在客户,目的是保留有用的数据并删除任何个人信息——电子邮件地址、姓名等,同时将30000多条潜在客户保存到几十个文件中,以便于访问 因此,我的第一个脚本打开每个单独的lead文件-30000+-根据文件中的时间戳确定捕获日期。然后,它将该结果保存到dict中的相应键。当所有数据聚合到此dict中时,将使用json.dumps写入文本文件 dict的结构是:Python&;JSON:ValueError:Unterminated字符串起始于:,json,python-2.7,Json,Python 2.7,我已经阅读了多篇关于这一点的StackOverflow文章,以及谷歌前十大搜索结果中的大部分。我的问题不同之处在于,我使用python中的一个脚本来创建JSON文件。下一个脚本在10分钟后运行,无法读取该文件 简短版本,我为我的在线业务生成潜在客户。为了更好地分析这些潜在客户,我正在尝试学习python。我正在搜寻2年的潜在客户,目的是保留有用的数据并删除任何个人信息——电子邮件地址、姓名等,同时将30000多条潜在客户保存到几十个文件中,以便于访问 因此,我的第一个脚本打开每个单独的lead文
addData['lead']['July_2013'] = { ... }
其中“lead”键可以是lead、partial和其他一些键,“July_2013”键显然是基于日期的键,可以是整月和2013年或2014年的任意组合,可以追溯到“July_2013”
完全错误如下:
ValueError: Unterminated string starting at: line 1 column 9997847 (char 9997846)
但我已经手动查看了该文件,我的IDE显示该文件中只有76655个字符。那么它是如何到达9997846的呢
失败的文件是要读取的第8个文件;通过json.loads读入后的其他7和所有其他文件都很好
Python说有一个未终止的字符串,所以我查看了失败文件中JSON的结尾,它看起来很好。我看到有人提到在JSON中使用换行符,但这个字符串都是一行。我已经看到了对\vs\的提及,但在快速查看整个文件时,我没有看到任何内容。其他文件确实有\并且读取良好。这些文件都是由json.dumps创建的
我无法发布该文件,因为其中仍包含个人信息。手动尝试验证76000字符文件的JSON实际上是不可行的
关于如何调试的想法将不胜感激。同时,我将尝试重建文件,看看这是否不是一次性的错误,而是需要一段时间
- Python2.7通过Spyder和Anaconda
- Windows 7 Pro
from p2p.basic import files as f
from p2p.adv import strTools as st
from p2p.basic import strTools as s
import os
import json
import copy
from datetime import datetime
import time
global leadDir
global archiveDir
global aggLeads
def aggregate_individual_lead_files():
"""
"""
# Get the aggLead global and
global aggLeads
# Get all the Files with a 'lead' extension & aggregate them
exts = [
'lead',
'partial',
'inp',
'err',
'nobuyer',
'prospect',
'sent'
]
for srchExt in exts:
agg = {}
leads = f.recursiveGlob(leadDir, '*.cd.' + srchExt)
print "There are {} {} files to process".format(len(leads), srchExt)
for lead in leads:
# Get the Base Filename
fname = f.basename(lead)
#uniqID = st.fetchBefore('.', fname)
#print "File: ", lead
# Get Lead Data
leadData = json.loads(f.file_get_contents(lead))
agg = agg_data(leadData, agg, fname)
aggLeads[srchExt] = copy.deepcopy(agg)
print "Aggregate Top Lvl Keys: ", aggLeads.keys()
print "Aggregate Next Lvl Keys: "
for key in aggLeads:
print "{}: ".format(key)
for arcDate in aggLeads[key].keys():
print "{}: {}".format(arcDate, len(aggLeads[key][arcDate]))
# raw_input("Press Enter to continue...")
def agg_data(leadData, agg, fname=None):
"""
"""
#print "Lead: ", leadData
# Get the timestamp of the lead
try:
ts = leadData['timeStamp']
leadData.pop('timeStamp')
except KeyError:
return agg
leadDate = datetime.fromtimestamp(ts)
arcDate = leadDate.strftime("%B_%Y")
#print "Archive Date: ", arcDate
try:
agg[arcDate][ts] = leadData
except KeyError:
agg[arcDate] = {}
agg[arcDate][ts] = leadData
except TypeError:
print "Timestamp: ", ts
print "Lead: ", leadData
print "Archive Date: ", arcDate
return agg
"""
if fname is not None:
archive_lead(fname, arcDate)
"""
#print "File: {} added to {}".format(fname, arcDate)
return agg
def archive_lead(fname, arcDate):
# Archive Path
newArcPath = archiveDir + arcDate + '//'
if not os.path.exists(newArcPath):
os.makedirs(newArcPath)
# Move the file to the archive
os.rename(leadDir + fname, newArcPath + fname)
def reformat_old_agg_data():
"""
"""
# Get the aggLead global and
global aggLeads
aggComplete = {}
aggPartial = {}
oldAggFiles = f.recursiveGlob(leadDir, '*.cd.agg')
print "There are {} old aggregate files to process".format(len(oldAggFiles))
for agg in oldAggFiles:
tmp = json.loads(f.file_get_contents(agg))
for uniqId in tmp:
leadData = tmp[uniqId]
if leadData['isPartial'] == True:
aggPartial = agg_data(leadData, aggPartial)
else:
aggComplete = agg_data(leadData, aggComplete)
arcData = dict(aggLeads['lead'].items() + aggComplete.items())
aggLeads['lead'] = arcData
arcData = dict(aggLeads['partial'].items() + aggPartial.items())
aggLeads['partial'] = arcData
def output_agg_files():
for ext in aggLeads:
for arcDate in aggLeads[ext]:
arcFile = leadDir + arcDate + '.cd.' + ext + '.agg'
if f.file_exists(arcFile):
tmp = json.loads(f.file_get_contents(arcFile))
else:
tmp = {}
arcData = dict(tmp.items() + aggLeads[ext][arcDate].items())
f.file_put_contents(arcFile, json.dumps(arcData))
def main():
global leadDir
global archiveDir
global aggLeads
leadDir = 'D://Server Data//eagle805//emmetrics//forms//leads//'
archiveDir = leadDir + 'archive//'
aggLeads = {}
# Aggregate all the old individual file
aggregate_individual_lead_files()
# Reformat the old aggregate files
reformat_old_agg_data()
# Write it all out to an aggregate file
output_agg_files()
if __name__ == "__main__":
main()
以下是读取代码:
from p2p.basic import files as f
from p2p.adv import strTools as st
from p2p.basic import strTools as s
import os
import json
import copy
from datetime import datetime
import time
global leadDir
global fields
global fieldTimes
global versions
def parse_agg_file(aggFile):
global leadDir
global fields
global fieldTimes
try:
tmp = json.loads(f.file_get_contents(aggFile))
except ValueError:
print "{} failed the JSON load".format(aggFile)
return False
print "Opening: ", aggFile
for ts in tmp:
try:
tmpTs = float(ts)
except:
print "Timestamp: ", ts
continue
leadData = tmp[ts]
for field in leadData:
if field not in fields:
fields[field] = []
fields[field].append(float(ts))
def determine_form_versions():
global fieldTimes
global versions
# Determine all the fields and their start and stop times
times = []
for field in fields:
minTs = min(fields[field])
fieldTimes[field] = [minTs, max(fields[field])]
times.append(minTs)
print 'Min ts: {}'.format(minTs)
times = set(sorted(times))
print "Times: ", times
print "Fields: ", fieldTimes
versions = {}
for ts in times:
d = datetime.fromtimestamp(ts)
ver = d.strftime("%d_%B_%Y")
print "Version: ", ver
versions[ver] = []
for field in fields:
if ts in fields[field]:
versions[ver].append(field)
def main():
global leadDir
global fields
global fieldTimes
leadDir = 'D://Server Data//eagle805//emmetrics//forms//leads//'
fields = {}
fieldTimes = {}
aggFiles = f.glob(leadDir + '*.lead.agg')
for aggFile in aggFiles:
parse_agg_file(aggFile)
determine_form_versions()
print "Versions: ", versions
if __name__ == "__main__":
main()
所以我想出来了。。。我发布这个答案只是为了防止其他人犯同样的错误 首先,我找到了一个工作,但我不知道为什么这样做有效。根据我的原始代码,这里是我的
文件\u获取\u内容
函数:
def file_get_contents(fname):
if s.stripos(fname, 'http://'):
import urllib2
return urllib2.urlopen(fname).read(maxUrlRead)
else:
return open(fname).read(maxFileRead)
我通过以下方式使用它:
tmp = json.loads(f.file_get_contents(aggFile))
这失败了,一次又一次。然而,当我试图让Python至少给我一个JSON字符串来完成一个测试时,我遇到了JSON.load
vsJSON.load
。所以我尝试了这个:
a = open('D://Server Data//eagle805//emmetrics//forms//leads\July_2014.cd.lead.agg')
b = json.load(a)
虽然我还没有在我的整个代码中测试这个输出,但这个代码块实际上读取了文件,解码了JSON,甚至可以在不破坏Spyder的情况下显示数据。Spyder中的变量explorer显示b是一个大小为1465的dict,这正是它应该拥有的记录数。从dict结尾显示的文本部分看起来都不错。所以总的来说,我对数据被正确解析有相当高的信心
当我编写file\u get\u contents
函数时,我看到了一些建议,我总是提供最大读取字节数,以防止Python挂起错误返回。maxReadFile
的值为1E7
。当我手动将maxReadFile
设置为1E9
时,一切正常。结果表明,该文件的字节数略低于1.2E7。因此,读取文件得到的字符串不是文件中的完整字符串,因此是无效的JSON
通常我会认为这是一个bug,但很明显,在打开和读取文件时,为了进行内存管理,您需要一次只读取一个块。因此,关于maxReadFile
值,我自己的短视让我受到了伤害。错误消息是正确的,但却让我陷入了白费力气
希望这能为其他人节省一些时间。我也遇到了同样的问题。事实证明,文件的最后一行不完整,可能是由于下载突然停止,因为我发现有足够的数据,只是在终端上停止了下载过程。如果有人和我一样在这里,如果您正在处理表单请求中的
json
,请检查是否有内容长度
头集。因为那个标题,我得到了这个错误。我使用了JSON美化,发现JSON变得相当大,这导致了这个错误。我在导入我创建的JSON文件时遇到了相同的问题,但是当我导入另一个JSON文件时,它甚至可以工作,而不必更改代码中的任何内容。在我创建的json文件中,我发现不同之处在于内容在一行上
产生这种形状的原因是,我在编写文件时将字典转储如下:
with open("sample.json", "w") as outfile:
json.dump(dictionary, outfile)
但有一次,我把字典一个人扔了,然后写了下来:
json_object = json.dumps(dictionary, indent = 4)
with open("sample.json", "w") as outfile:
outfile.write(json_object)
我有已知的json文件的标准形状:
因此,请了解如何使用此json文件并导入它,我们不会遇到问题。您需要向我们展示您的代码。如果它有个人信息,删除信息。你真的想让我发布一个包含76000个字符的JSON文件吗?该代码适用于除此之外的所有其他文件。所以我确信这与保存的一个字段有关。它包含了几千人的个人信息。我可以手动将数据输入到一个新文件中,几乎和我从这个文件中删除个人数据一样快。除非PHP或其他东西可以打开这个文件,否则删除操作必须手动完成。如果没有人能提供智慧的指针