Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在MapReduce作业中导入自定义模块?_Python_Mapreduce_Hadoop Streaming - Fatal编程技术网

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。这很有效,谢谢!