Python mrjob:示例如何自动知道如何在文本文件中查找行?

Python mrjob:示例如何自动知道如何在文本文件中查找行?,python,mapreduce,mrjob,Python,Mapreduce,Mrjob,我正试图更好地理解mrjob的例子 from mrjob.job import MRJob class MRWordFrequencyCount(MRJob): def mapper(self, _, line): yield "chars", len(line) yield "words", len(line.split()) yield "lines", 1 def reducer(self, key, values):

我正试图更好地理解mrjob的例子

from mrjob.job import MRJob  
class MRWordFrequencyCount(MRJob):

    def mapper(self, _, line):
        yield "chars", len(line)
        yield "words", len(line.split())
        yield "lines", 1

    def reducer(self, key, values):
        yield key, sum(values)
if __name__ == '__main__':
    MRWordFrequencyCount.run()
我自己管理它

$ python word_count.py my_file.txt
它可以像预期的那样工作,但我不明白它是如何自动知道它将读取一个文本文件并按每行分割的。我也不确定
\uu
的作用

据我所知,
mapper()
为每行生成三个键/值对,对吗?如果我想处理文件夹中的每个文件,该怎么办

reducer()
自动知道如何将每个键的值相加


如果我想通过MapReduce运行单元测试,映射器和reducer会是什么样子?有必要吗

我对mrjob了解不多,所以我要做一些假设。首先,u意味着忽略密钥(在谷歌搜索后验证)。其次,我假设它可以在逗号分隔的文件列表或目录上工作。接下来,这段代码没有设置,可能是因为这些是默认的方法名。我敢肯定,如果你给你的制图器或减缩器命名了不同的东西,mrjob不会自动拾取它


我找到了一些例子。

映射器方法接收一个已经从输入文本中解析出来的键值对。mrjob使用Hadoop流,每个输入文本被新行字符分割,然后根据使用的输入协议将每行分割为键值对。这是框架为您处理的事情,因此您不必做任何繁重的工作;您可以假设您将获得正确的键和值

但是,您确实需要指定指定的输入文本文件的类型。例如,如果键和/或值不是纯文本(如原始问题中所示),而是序列化的JSON,则使用JSONProtocol/JSONValueProtocol等,而不是默认的RawValueProtocol

对于初始映射器,每一行都被读入值中(通过RawValueProtocol),所以这就是您不接收密钥的原因。对于未使用的伪变量,使用
只是一种Python约定。(然而,
\uu
实际上是Python变量的有效名称。您可以这样做
a=3;\u=2;b=a+\u
。亵渎神明,不是吗?)

mrjob可以接受多个输入文件。例如,你可以这样做

$ python wordcount.py text1.txt text2.txt
如果希望所有文本文件都作为mrjob作业的输入,可以执行以下操作

$ python wordcount.py inputdir/*.txt
或者干脆

$ python wordcount.py inputdir
所有选定的文件都用作输入

reducer接收的是一个键和与该键关联的所有值的迭代器。例如,reducer方法中的变量
value
是一个迭代器。如果您想对所有值执行某些操作,则需要对所有值进行迭代。在问题中的特定示例中,内置函数
sum
可以将迭代器作为参数,这就是为什么您可以一次性完成它。但它实际上类似于
sum([value-for-value-in-values])

我真的不知道如何对mrjob脚本进行单元测试。在生产运行之前,我通常只测试了一小部分测试数据

from mrjob.job import MRJob

class MRRatingCounter(MRJob):
    def mapper(self, key, line):


        (userID, movieID, rating, timestamp) = line.split('\t')
        yield rating, 1

    def reducer(self, rating, occurences):
        yield rating, sum(occurences)

if __name__ == '__main__':
    MRRatingCounter.run()
因此,请根据上述讨论纠正我:

如果我错了,请纠正我,因此在这种情况下,key取输入文件的值。在这种情况下,我可以这样在脑海中阅读它:

def映射器(self{这是对象/实例},键{输入文本文件在本例中是文件名,请更正me ml-100k/u.data,行{这是每次从数据文件尝试传递到映射器()的数据。,)

我试图学习的Udemy中的另一个代码如原始问题所述: mrfriendsbage(MRJob)类:

如果name='main': mrfriendsbage.run()


所以,如果它正在解析json文件,它应该看起来像
{'key1':'value1'}{'key2':'value2'}
其中,txt文件只有
value1\n value2\n value3\n
?在mrjob实现中,键和值可以分别是JSON对象。事实上,我认为它是通过JSONProtocol内部传递的。在序列化时,键-值对由制表符分隔。因此,在JSON协议中,一行类似于
“key”\t{“somelist”:[1,2,3]}\n
例如。这实际上就是为什么输出的键是双引号的原因,因为它是以JSON的字符串形式输出的。对于初始输入,如果使用JSONValueProtocol,那么您希望输入文件看起来像
{“L1”:1}\n{“L2”:2}\n{“L3”:3}
等等。每行只包含该协议的一个值。实际上,我建议您阅读关于输入协议的mrjob文档。这是必要和有用的,但如果您不熟悉输入/输出/键值的内部处理方式,则可能会混淆。谢谢您,这非常有帮助。起初我在阅读时有点困惑json协议中的位
def mapper(self, _, line):
    (ID, name, age, numFriends) = line.split(',')
    yield age, float(numFriends)

def reducer(self, age, numFriends):
    total = 0
    numElements = 0
    for x in numFriends:
        total += x
        numElements += 1

    yield age, total / numElements