繁体   English   中英

如何在MapReduce作业中导入自定义模块?

[英]How to import a custom module in a MapReduce job?

我在main.py定义了一个MapReduce作业,它从lib.py导入lib模块。 我使用Hadoop Streaming将此作业提交到Hadoop集群,如下所示:

hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar -files lib.py,main.py 
    -mapper "./main.py map" -reducer "./main.py reduce" 
    -input input -output output

根据我的理解,这应该将main.pylib.py放入每台计算机上的分布式缓存文件夹中 ,从而使模块lib可用于main 但它没有发生:从日志中我看到文件真的被复制到同一个目录,但是main无法导入lib ,抛出了ImportError

为什么会发生这种情况,我该如何解决?

UPD。 将当前目录添加到路径不起作用:

import sys    
sys.path.append(os.path.realpath(__file__))
import lib
# ImportError

但是,手动加载模块可以解决问题:

import imp
lib = imp.load_source('lib', 'lib.py')

但这不是我想要的。 那么为什么Python解释器会在同一目录中看到其他.py文件,但却无法导入它们? 请注意,我已经尝试将空的__init__.py文件添加到同一目录而不起作用。

我将问题发布到Hadoop用户列表,最后找到答案。 事实证明,Hadoop并不真正将文件复制到命令运行的位置,而是为它们创建符号链接 反过来,Python无法使用符号链接,因此无法将lib.py识别为Python模块。

这里简单的解决方法是将main.pylib.py放在同一目录中,以便将目录的符号链接放入MR作业工作目录,而两个文件实际上位于同一目录中。 所以我做了以下事情:

  1. main.pylib.py放入app目录。
  2. main.py我直接使用了lib.py ,也就是说,import string就是

    导入lib

  3. 使用-files选项上传的app目录。

所以,final命令看起来像这样:

hadoop jar /usr/lib/hadoop-mapreduce/hadoop-streaming.jar -files app 
       -mapper "app/main.py map" -reducer "app/main.py reduce" 
       -input input -output output 

当Hadoop-Streaming启动python脚本时,python脚本的路径就是脚本文件的真实位置。 但是,hadoop以'./'开头,而你的lib.py(它是一个符号链接)也是'./'。 因此,在导入lib.py之前尝试添加'sys.path.append(“./”)',如下所示: import sys sys.path.append('./') import lib

-files-archive开关只是快捷方式Hadoop的分布式缓存 (DC),更通用的机制,也允许上传,并在拉链,焦油和TGZ /的tar.gz格式的自动解压缩档案。 如果您的库是由结构化Python包实现的,而不是单个模块,则后一个功能就是您想要的。

我们在发布1.0.0-rc1后直接在Pydoop中支持这个,你可以在其中简单地构建一个mypkg.tgz存档并运行你的程序:

pydoop submit --upload-archive-to-cache mypkg.tgz [...]

相关文档位于http://crs4.github.io/pydoop/self_contained.html ,这是一个完整的工作示例(需要轮子 ): https//github.com/crs4/pydoop/tree/master/examples/自我包容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM