PySpark:过滤掉RDD元素失败' NoneType'对象不可迭代

时间:2015-03-11 20:21:58

标签: apache-spark pyspark

我希望filter输出RDD的字段' status'不等于' OK'。我从HDFS上的一组CSV文件创建我的RDD,然后在尝试map之前使用filter获取我想要的结构:

import csv, StringIO    

files = "/hdfs_path/*.csv"

fields = ["time", "status"]

dial = "excel"

default = {'status': 'OK', 'time': '2014-01-01  00:00:00'}

def loadRecord(line, fieldnames, dialect):
    input = StringIO.StringIO(line)
    reader = csv.DictReader(input, fieldnames = fieldnames, dialect = dialect)
    try:
        line = reader.next()
        if line is None:
            return default
        else:
            return line
    except:
        return default

harmonics = sc.textFile(files) \
              .map(lambda x: loadRecord(x, fields, dial)) \
              .filter(lambda x: "OK" not in x['status'])

我可以对此RDD做其他事情 - 例如另一个mapget只有某些字段等。但是,当我使用filter运行我的代码时,其中一个任务总是失败,我的filter lambda中出现异常功能:

'NoneType object is not iterable'

我认为这意味着filter lambda正在收到None,因此我将代码添加到loadRecord以避免返回None。但是,我仍然得到同样的错误。它确实适用于小样本数据集,但我的实际数据足够大,以至于我不确定如何检测它的哪个部分可能导致问题。

任何意见都赞赏!

2 个答案:

答案 0 :(得分:3)

首先,使用map(lambda x: loadRecord(x, fields, dial))重新定位map(lambda x: (x, loadRecord(x, fields, dial))) - 这样就可以保存原始记录和已解析的记录。

其次,用filter()替换flatMap(test_function)调用并定义test_function测试输入的方式,如果第二个传递的参数是None(解析记录),它将返回第一个

这样你就会得到导致问题的输入行,并在本地测试你的脚本。一般情况下,我会添加一行global default作为loadRecord函数的第一行

答案 1 :(得分:0)

0x0FFF的答案为基础,我能够运行我的代码。我还没有看到违规文件的违规行,但我比我更接近。这就是我所做的,从我的问题中的代码开始:

def checkNone(x):
    try:
        return "OK" not in x['status']
    except:
        return True

harmonics = sc.textFile(files) \
              .map(lambda x: loadRecord(x, fields, dial)) \
              .filter(lambda x: checkNone(x))