我在 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 并没有真正将文件复制到命令运行的位置,而是为它们创建符号链接(symbolic link)。反过来,Python 不能使用符号链接(symbolic link),因此不能将 lib.py 识别为 Python 模块。

这里的简单解决方法是将main.pylib.py放在同一个目录中,这样符号链接(symbolic link)到该目录 放置在 MR 作业工作目录中,而两个文件在物理上位于同一目录中。所以我做了以下事情:

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

    导入库

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

所以,最后的命令是这样的:

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  


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!