pyspark中的--files选项不起作用

时间:2017-11-08 18:54:42

标签: apache-spark pyspark yarn

我在命令行中尝试class Solution: def maximumProduct(self, nums): a,b,c = d,e,_ = sorted(nums[:3]) for x in nums[3:]: if x >= c: a,b,c = b,c,x elif x >= b: a,b = b,x elif x >= a: a = x if x <= d: d,e = x,d elif x < e: e = x return max(a*b*c,c*d*e) 选项(没有任何问题)和sc.addFile选项(失败)。

运行1:spark_distro.py

--files

外部包:external_package.py

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

def import_my_special_package(x):
    from external_package import external
    ext = external()
    return ext.fun(x)

conf = SparkConf().setAppName("Using External Library")
sc = SparkContext(conf=conf)
sc.addFile("/local-path/readme.txt")
with open(SparkFiles.get('readme.txt')) as test_file:
    lines = [line.strip() for line in test_file]
print(lines)
int_rdd = sc.parallelize([1, 2, 4, 3])
mod_rdd = sorted(int_rdd.filter(lambda z: z%2 == 1).map(lambda x:import_my_special_package(x)))

README.TXT

class external(object):
    def __init__(self):
        pass
    def fun(self,input):
        return input*2

spark-submit命令

MY TEXT HERE

输出:按预期工作

spark-submit \
  --master yarn-client \
  --py-files /path to local codelib/external_package.py  \
  /local-pgm-path/spark_distro.py  \
  1000

但是如果我尝试使用--files(而不是sc.addFile)选项从命令行传递文件(readme.txt),那么它就失败了。 如下所示。

运行2:spark_distro.py

['MY TEXT HERE']

external_package.py 与上述相同

spark submit

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

def import_my_special_package(x):
    from external_package import external
    ext = external()
    return ext.fun(x)

conf = SparkConf().setAppName("Using External Library")
sc = SparkContext(conf=conf)
with open(SparkFiles.get('readme.txt')) as test_file:
    lines = [line.strip() for line in test_file]
print(lines)
int_rdd = sc.parallelize([1, 2, 4, 3])
mod_rdd = sorted(int_rdd.filter(lambda z: z%2 == 1).map(lambda x: import_my_special_package(x)))

输出:

spark-submit \
  --master yarn-client \
  --py-files /path to local codelib/external_package.py  \
  --files /local-path/readme.txt#readme.txt  \
  /local-pgm-path/spark_distro.py  \
  1000

Traceback (most recent call last): File "/local-pgm-path/spark_distro.py", line 31, in <module> with open(SparkFiles.get('readme.txt')) as test_file: IOError: [Errno 2] No such file or directory: u'/tmp/spark-42dff0d7-c52f-46a8-8323-08bccb412cd6/userFiles-8bd16297-1291-4a37-b080-bbc3836cb512/readme.txt' sc.addFile用于同一目的吗?有人可以分享你的想法。

1 个答案:

答案 0 :(得分:8)

我终于找到了问题,而且确实是一个非常微妙的

正如所怀疑的那样,两个选项(sc.addFile--files等效,这是(诚然非常巧妙地)暗示文档(强调添加):

  

addFile (路径,递归=假)
  使用此Spark作业在每个节点上添加要下载的文件。

     

--files文件
  以逗号分隔的文件列表,放在工作中                                 每个执行者的目录。

简单地说,虽然添加了sc.addFile的文件对执行程序和驱动程序都可用,但添加了--files的文件只对执行程序可用;因此,当尝试从驱动程序访问它们时(如OP中的情况),我们得到No such file or directory错误。

让我们确认一下(摆脱OP中所有不相关的--py-files1000内容):

<强> test_fail.py

from pyspark import SparkContext, SparkConf
from pyspark import SparkFiles

conf = SparkConf().setAppName("Use External File")
sc = SparkContext(conf=conf)
with open(SparkFiles.get('readme.txt')) as test_file:  
    lines = [line.strip() for line in test_file]
print(lines)

测试:

spark-submit --master yarn \
             --deploy-mode client \
             --files /home/ctsats/readme.txt \
             /home/ctsats/scripts/SO/test_fail.py

结果:

[...]
17/11/10 15:05:39 INFO yarn.Client: Uploading resource file:/home/ctsats/readme.txt -> hdfs://host-hd-01.corp.nodalpoint.com:8020/user/ctsats/.sparkStaging/application_1507295423401_0047/readme.txt
[...]
Traceback (most recent call last):
  File "/home/ctsats/scripts/SO/test_fail.py", line 6, in <module>
    with open(SparkFiles.get('readme.txt')) as test_file:
IOError: [Errno 2] No such file or directory: u'/tmp/spark-8715b4d9-a23b-4002-a1f0-63a1e9d3e00e/userFiles-60053a41-472e-4844-a587-6d10ed769e1a/readme.txt'

在上面的脚本test_fail.py中,请求访问文件readme.txt驱动程序程序;让我们更改脚本,以便为执行者 test_success.py )请求访问权限:

from pyspark import SparkContext, SparkConf

conf = SparkConf().setAppName("Use External File")
sc = SparkContext(conf=conf)

lines = sc.textFile("readme.txt") # run in the executors
print(lines.collect())

测试:

spark-submit --master yarn \
             --deploy-mode client \
             --files /home/ctsats/readme.txt \
             /home/ctsats/scripts/SO/test_success.py

结果:

[...]
17/11/10 15:16:05 INFO yarn.Client: Uploading resource file:/home/ctsats/readme.txt -> hdfs://host-hd-01.corp.nodalpoint.com:8020/user/ctsats/.sparkStaging/application_1507295423401_0049/readme.txt
[...]
[u'MY TEXT HERE']

另请注意,此处我们不需要SparkFiles.get - 该文件可随时访问。

如上所述,sc.addFile将在两种情况下都有效,即当驱动程序或执行程序请求访问时(已测试但未在此处显示)。

关于命令行选项的顺序:正如我所说的那样elsewhere,所有与Spark相关的参数必须在要执行的脚本之前;可以说,--files--py-files的相对顺序无关紧要(将其作为练习)。

使用 Spark 1.6.0 &amp;进行测试的 2.2.0

更新(评论后):似乎我的fs.defaultFS设置也指向HDFS:

$ hdfs getconf -confKey fs.defaultFS
hdfs://host-hd-01.corp.nodalpoint.com:8020

但是让我关注这里的森林(而不是树木),并解释为什么整个讨论仅仅是学术上的兴趣

使用--files标志传递要处理的文件 是不好的做法;事后来看,我现在可以看到为什么我几乎找不到在线使用的参考资料 - 可能没有人在实践中使用它,并且有充分的理由。

(请注意,我不是在谈论--py-files,它扮演着不同的合法角色。)

由于Spark是一个分布式处理框架,运行在集群和分布式文件系统(HDFS)上,最好的办法是将所有文件都处理到HDFS中 - 期间 。 &#34;自然&#34; Spark要处理的文件的位置是HDFS,而不是本地FS - 尽管有一些玩具示例仅使用本地FS进行演示。更重要的是,如果您希望将来有一段时间将部署模式更改为cluster,您将发现默认情况下,群集对本地路径和文件一无所知,并且理所当然所以...