Python - Readline跳过字符

时间:2015-07-09 06:39:43

标签: python json

我在解析大文本文件中的json对象时遇到了一个奇怪的问题,我找到的解决方案并没有多大意义。我正在使用以下脚本。它复制bz2文件,解压缩它们,然后将每一行解析为json对象。

import os, sys, json

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
#              USER INPUT
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

args = sys.argv
extractDir = outputDir = ""

if (len(args) >= 2):
    extractDir = args[1]
else:
    extractDir = raw_input('Directory to extract from: ')

if (len(args) >= 3):
    outputDir = args[2]
else:
    outputDir = raw_input('Directory to output to: ')

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   
#            RETRIEVE FILE
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   

tweetModel = [u'id', u'text', u'lang', u'created_at', u'retweeted', u'retweet_count', u'in_reply_to_user_id', u'coordinates', u'place', u'hashtags', u'in_reply_to_status_id']

filenames = next(os.walk(extractDir))[2]
for file in filenames:
    if file[-4:] != ".bz2":
        continue

    os.system("cp " + extractDir + '/' + file + ' ' + outputDir)
    os.system("bunzip2 " + outputDir + '/' + file)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   
#            PARSE DATA
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   

    input = open (outputDir + '/' + file[:-4], 'r')
    output = open (outputDir + '/p_' + file[:-4], 'w+')

    for line in input.readlines():
        try:
            tweet = json.loads(line)
            for field in enumerate(tweetModel):
                if tweet.has_key(field[1]) and tweet[field[1]] != None:
                    if field[0] != 0:
                        output.write('\t')
                    fieldData = tweet[field[1]]
                    if not isinstance(fieldData, unicode):
                        fieldData = unicode(str(fieldData), "utf-8")

                    output.write(fieldData.encode('utf8'))
                else:
                    output.write('\t')

        except ValueError as e:
            print ("Parse Error: " + str(e))
            print line
            line = input.readline()
            quit()
            continue

        print "Success! " + str(len(line))
        input.flush()

        output.write('\n')

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   
#          REMOVE OLD FILE
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=   

    os.system("rm " +  outputDir + '/' + file[:-4])

在读取for line in input.readlines():循环中的某些行时,这些行偶尔会在不一致的位置被截断。由于换行符也被截断,因此它将继续读取,直到它在下一个json对象的末尾找到换行符。结果是一个不完整的json对象,后跟一个完整的json对象,解析器都将其视为一行。我找不到这个问题的原因,但我确实发现将循环更改为

filedata = input.read()
for line in filedata.splitlines():

的工作。有谁知道这里发生了什么?

1 个答案:

答案 0 :(得分:2)

在查看file.readlines和string.splitlines的源代码后,我想我看到了什么。 注意:这是python 2.7源代码,所以如果你正在使用另一个版本...也许这个答案可能没有。

readlines使用函数Py_UniversalNewlineFread来测试换行符splitlines使用仅测试\ n或\ r \ n的常量STRINGLIB_ISLINEBREAK。我怀疑Py_UniversalNewlineFread在文件流中拾取一些字符作为换行符,当它不是真正意图作为换行符时,可能来自编码..我不知道......但当你只是转储所有相同的数据到一个字符串,splitlines检查它\ r和\ n theres没有匹配,所以splitlines继续前进,直到遇到真正的换行符并且你得到你想要的行。