Python 如何在MapReduce作业中导入自定义模块?
我在Python 如何在MapReduce作业中导入自定义模块?,python,mapreduce,hadoop-streaming,Python,Mapreduce,Hadoop Streaming,我在main.py中定义了一个MapReduce作业,它从lib.py导入lib模块。我使用Hadoop流将此作业提交到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.py
中定义了一个MapReduce作业,它从lib.py
导入lib
模块。我使用Hadoop流将此作业提交到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.py
和lib.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
文件,但无法导入它们呢?请注意,我已经尝试将一个空的\uuuu init\uuuu.py
文件添加到同一个目录中,但没有效果。我将问题发布到Hadoop用户列表,最后找到了答案。事实证明,Hadoop并没有真正将文件复制到命令运行的位置,而是为它们创建符号链接。反过来,Python不能使用符号链接,因此不能将lib.py
识别为Python模块
简单的解决方法是将main.py
和lib.py
放在同一个目录中,这样指向该目录的符号链接就会放在MR作业工作目录中,而这两个文件实际上都在同一个目录中。因此,我做了以下工作:
main.py
和lib.py
放入app
目录李>
main.py
中,我直接使用了lib.py
,也就是说,导入字符串只是
导入库-文件
选项上载应用程序
目录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(“./”),如下所示:
导入系统
sys.path.append(“./”)
导入库
-files
和-archive
开关只是Hadoop(DC)的快捷方式,这是一种更通用的机制,还允许以zip、tar和tgz/tar.gz格式上传和自动解包归档文件。如果库不是由单个模块实现的,而是由结构化Python包实现的,那么后一个特性就是您想要的
我们从1.0.0-rc1版开始就直接支持这一点,您只需构建mypkg.tgz
archive并以以下方式运行您的程序:
pydoop submit --upload-archive-to-cache mypkg.tgz [...]
相关文档位于,这是一个完整的工作示例(需要):.您是否在
main.py
中检查了sys.path
,以确保工作目录包含在其中?@lmjohns3:是的,工作目录位于类路径上。顺便说一句,它不是自动包含在运行脚本中吗?(只是好奇)我相信这对于在命令行上启动的Python脚本是正确的,但是Hadoop流可能会以另一种方式启动Python解释器(不是很确定)。不管怎样,我仍然认为这听起来像是一个路径问题。有关以不同方式分发模块的一种可能性,请参阅。或者,尝试将命令写入shell脚本,并将其传递给-mapper
和-reducer
命令行参数。@lmjohns3:是的,我已经看到了模块的诀窍,但它对main
设置了一些限制,同时我正在尝试尽可能简单地导入。关键是要创建一个可分发的库,您只需导入
。使用-files选项上载几十个文件在我的hadoop环境中不起作用。我使用的是Thread,它似乎不支持所选答案使用的-files。这很有效,谢谢!