详解mrjob输入输出协议(Protocols)

本文详细解析了mrjob框架中的输入输出协议,包括默认协议、数据流实例、如何为作业指定协议以及如何编写自定义协议。通过示例展示了如何处理数据流,以及如何根据需求定制协议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先翻译一下官方文档,然后写一个小的案例进行理解。更详细的内容可以参考最新的文档和源码(https://github.com/Yelp/mrjob)

输入输出协议

官方链接:https://pythonhosted.org/mrjob/guides/writing-mrjobs.html#protocols

mrjob假设所有数据都是换行符分隔的字节。它使用protocols序列和反序列化这些字节。每个job(作业)都一个输入protocol,一个输出procotol和一个内部procotol
一个procotol具有read()方法和write()方法。该 read()方法将字节转换为python对象的键值(key和value)对。该write()方法将一对Python对象(表示key和value组成的键值对)转换回字节。

输入procotol用于读取字节并发送给第一个mapper(或者reducer,如果第一步骤中不使用mapper)。输出procotol将最后一步输出以字节形式输出到输出文件。内部procotol转换一个步骤的输出到下一个步骤的输入,如果该作业具有一个以上的步骤。
您可以指定作业使用的procotol,如下所示:

class MyMRJob(mrjob.job.MRJob):

    # these are the defaults
    INPUT_PROTOCOL = mrjob.protocol.RawValueProtocol
    INTERNAL_PROTOCOL = mrjob.protocol.JSONProtocol
    OUTPUT_PROTOCOL = mrjob.protocol.JSONProtocol

默认输入协议是RawValueProtocol,它只把每一行读成一个str。(该行不会有尾随换行符,因为MRJob会将它删除 )。因此,默认情况下,在作业的第一步可以看到将每行输入转化为(None, line)的键值对。

默认输出和内部协议都是JSONProtocol,它读取和写入由制表符分隔的JSON字符串。(默认情况下,Hadoop Streaming在对数据进行排序时使用制表符分隔一行内的键值对。)

如果你的头有点疼,可以这样想:RawValueProtocol当你想读或写原始文本行时使用。JSONProtocol当你想要读取或写入键值对(JSON编码字节的键值对)时使用。

注意: Hadoop Streaming不使用JSON或mrjob协议。它只是通过对第一个制表符前面的内容进行字符串比较来对行进行分组。

可以通过查看mrjob.protocol(https://pythonhosted.org/mrjob/protocols.html#module-mrjob.protocol) 来了解mrjob内置协议的完整列表。

脚注:

  • [1] 经验丰富的Pythonistas可能会注意到,str在Python 2上是一个字节串,但在Python 3上是Unicode。这是对的!RawValueProtocol是两个不同协议之一的别名,具体取决于您的Python版本。
  • [2] JSONProtocol是四种不同实现之一的别名; 我们尝试使用(更快)ujson库(如果可用),如果没有,尝试rapidjson或者simplejson库。在前边都没有的情况下, 使用python内置json模块。
数据流实例

让我们从多步骤工作中重新审视我们的示例。它有两个步骤,并将纯文本文件作为输入

class MRMostUsedWord(MRJob):

    def steps(self):
        return [
            MRStep(mapper=self.mapper_get_words,
                   combiner=self.combiner_count_words,
                   reducer=self.reducer_count_words),
            MRStep
### Django 集成 MRJob 教程及调用示例 MRJob 是一个用于编写 Hadoop 流式作业的 Python 库,允许开发者轻松创建 MapReduce 任务。将其与 Django 结合可以实现基于 Web 的大数据处理应用。 --- #### 1. **安装依赖** 首先需要确保环境中有必要的库。可以通过以下命令安装 MRJob 和其他相关依赖: ```bash pip install mrjob==0.6.10 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com ``` 如果尚未安装 Django,则需一并完成安装: ```bash pip install django==1.11.7 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com ``` 验证两者是否正确安装: ```bash python -c "import mrjob; import django; print('mrjob version:', mrjob.__version__); print('django version:', django.get_version())" ``` --- #### 2. **配置 Django 项目结构** 在 Django 中集成 MRJob 可以通过视图函数触发 MapReduce 任务。下面是一个简单的项目目录结构示例: ``` my_django_project/ ├── manage.py ├── myapp/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations/ │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── views.py │ └── tasks.py # 存放 MRJob 类定义 └── my_django_project/ ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py ``` 其中 `tasks.py` 将保存 MRJob 的类定义。 --- #### 3. **定义 MRJob 类** 在 `myapp/tasks.py` 文件中定义一个简单的 MRJob 类。例如,统计输入数据中的单词数量: ```python from mrjob.job import MRJob from mrjob.step import MRStep class WordCount(MRJob): def mapper(self, _, line): for word in line.split(): yield (word.lower(), 1) def combiner(self, word, counts): yield (word, sum(counts)) def reducer(self, word, counts): yield (word, sum(counts)) if __name__ == '__main__': WordCount.run() ``` 这个类实现了三个阶段:Mapper、Combiner 和 Reducer。 --- #### 4. **在 Django 视图中调用 MRJob** 编辑 `views.py` 来运行 MRJob 并返回结果。这里展示如何通过 HTTP 请求触发改任务: ```python from django.http import JsonResponse from subprocess import Popen, PIPE import os def run_mrjob(request): if request.method != 'POST': return JsonResponse({'error': 'Invalid method'}, status=405) input_data = request.POST.get('input', None) if not input_data: return JsonResponse({'error': 'Missing input data'}, status=400) # 创建临时文件存储输入数据 temp_file_path = '/tmp/input.txt' with open(temp_file_path, 'w') as f: f.write(input_data) try: # 运行 MRJob process = Popen( ['python', './myapp/tasks.py', '-r', 'inline', temp_file_path], stdout=PIPE, stderr=PIPE ) output, error = process.communicate() if process.returncode != 0: return JsonResponse({'error': error.decode()}, status=500) result = {} lines = output.decode().splitlines() for line in lines: key, value = line.strip().rsplit('\t', 1) result[key] = int(value) return JsonResponse(result) finally: # 清理临时文件 if os.path.exists(temp_file_path): os.remove(temp_file_path) ``` 在这个例子中,`run_mrjob` 函数接收 POST 请求的数据作为输入,写入临时文件后调用 MRJob 脚本执行任务,并最终删除临时文件[^5]。 --- #### 5. **URL 映射** 为了使视图生效,还需在 `urls.py` 添加路由映射: ```python from django.conf.urls import url from . import views urlpatterns = [ url(r'^mrjob/$', views.run_mrjob, name='run_mrjob'), ] ``` 现在可以通过发送 POST 请求至 `/mrjob/` 接口来测试功能。 --- #### 6. **注意事项** - 当前示例使用 `-r inline` 参数让 MRJob 在单线程模式下运行,适合开发调试。生产环境下建议改为真正的 Hadoop 集群运行方式。 - 输入数据量较大时,考虑优化上传流程或将数据预存于 HDFS 上再指定路径给 MRJob 处理。 - 错误捕获部分可以根据实际需求进一步完善,增加日志记录等功能提升可维护性。 --- ### 总结 以上展示了如何将 MRJob 集成到 Django 项目中并通过 API 方式调用。这不仅有助于构建复杂的后台批处理逻辑,还能充分利用 Django 的强大生态体系简化前端交互设计。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值