在mapreduce作业中,我将产品名作为字符串参数传递给Map器。py脚本导入一个名为process.py的辅助脚本,该脚本对产品名称执行某些操作,并向Map器返回一些emit字符串。然后Map器将这些字符串发送到hadoop框架,以便reducer可以提取它们。除了以下几点外,一切正常:
py脚本包含一个查找值字典,我想将它从脚本内部移动到一个xml文件中,以便于更新。我已经在本地进行了测试,如果在process.py脚本中包含xml文件的windows路径,它就可以正常工作。但是,在hadoopmapreduce环境中测试这一点由于某些原因不起作用。
我曾尝试在process.py脚本中指定xml文档的hdfs路径,并尝试在mapreduce job命令中添加xml文档的名称作为-file参数,但都不起作用。
例如,在process.py中,我尝试了:
xml文件=r'appers@hdfs.network.com:/nfs\u home/appers/cnielsen/product\u lookups.xml'
和
xml\u file=r'/nfs\u home/appers/cnielsen/product\u lookups.xml'
在mapreduce命令中,我将xml文件的名称作为-file参数包含在内。例如:
... -文件product\u lookups.xml-reducer。。。
问题是:在mapreduce环境中,如何允许process.py脚本读取存储在hdfs上的xml文档?
2条答案
按热度按时间0x6upsns1#
下面是一个端到端的例子,它调整了上一个问题中提到的技巧,使之更适合您的问题。
python从hdfs读取文件作为流
这是一个小型的python-hadoop流应用程序,它读取键值对,对照hdfs中存储的xml配置文件检查键值,然后仅在键值与配置匹配时才发出值。匹配的逻辑被卸载到一个单独的process.py模块中,该模块使用对的外部调用从hdfs读取xml配置文件
hdfs dfs -cat
.首先,我们创建一个名为pythonapp的目录,其中包含实现的python源文件。稍后我们将在提交流作业时看到,我们将在
-files
争论。为什么我们要把这些文件放在一个中间目录中,而不是在目录中单独列出每个文件
-files
争论?这是因为当yarn将要在容器中执行的文件本地化时,它引入了一层符号链接间接寻址。python无法通过symlink正确加载模块。解决方案是将两个文件打包到同一个目录中。然后,当yarn对文件进行本地化时,symlink间接寻址是在目录级别完成的,而不是单个文件。由于主脚本和模块在物理上都在同一个目录中,python将能够正确地加载模块。这个问题更详细地解释了这个问题:如何在mapreduce作业中导入自定义模块?
Map器.py
流程.py
接下来,我们将2个文件放入hdfs/testdata是输入文件,包含制表符分隔的键值对/pythonappconf.xml是xml文件,我们可以在其中配置一个特定的密钥来匹配。
/测试数据
/pythonappconf.xml文件
既然我们已经准备好了
matchString
至foo
,并且由于我们的输入文件只包含一个键设置为foo
,我们希望运行作业的输出是包含键对应的值的单行foo
,即1
. 把它试运行一下,我们确实得到了预期的结果。另一种方法是在
-files
争论。这样,在python脚本启动之前,yarn将把xml文件作为本地化资源拉送到运行容器的各个节点。然后,python代码可以像打开工作目录中的本地文件一样打开xml文件。对于运行多个任务/容器的非常大的作业,这种技术可能比调用hdfs dfs -cat
从每个任务。为了测试这项技术,我们可以尝试不同版本的process.py模块。
流程.py
命令行调用更改为在中指定hdfs路径
-files
,再一次,我们看到了预期的结果。apachehadoop文档讨论了
-files
在这里本地拉hdfs文件的选项。http://hadoop.apache.org/docs/r2.7.1/hadoop-streaming/hadoopstreaming.html#working_with_large_files_and_archives
nkhmeac62#
感谢chris nauroth提供的上述答案。通过这篇文章,我想总结一下究竟是什么解决了我的问题。
他提供的第二个答案与我最初想做的非常接近。我发现我只需要做一些小的改变就可以让它正常工作。例如,在process.py脚本中,我之前尝试包含指向小查找xml的完整路径,如下所示:
xml_file = r'appers@hdfs.network.com:/nfs_home/appers/cnielsen/product_lookups.xml'
和xml_file = r'/nfs_home/appers/cnielsen/product_lookups.xml'
原来我只需要在process.py脚本中提供文件名,而不需要路径。例如:xml_file = 'product_lookups.xml'
然后,对于实际的hadoop命令,我之前尝试过这个命令,但没有成功:(在-mapper列表之后使用-file product\u lookups.xml)构造hadoop命令的正确方法是使用-files并在任何其他文件列表之前列出这个查找文件。例如,这起到了作用:
注意:尽管此页说明要像这样构造-files命令:
-files hdfs://host:fs_port/user/testfile.txt
如果我包含hdfs://或host:部分,这对我来说不起作用,从上面列出的实际命令可以看出。