web-dev-qa-db-ja.com

--pysparkのファイルオプションが機能しない

私は試した sc.addFileオプション(問題なく動作)および--filesコマンドラインからのオプション(失敗)。

実行1:spark_distro.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)))

外部パッケージ:external_package.py

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

readme.txt

MY TEXT HERE

spark-submitコマンド

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

出力:期待どおりに機能しています

['MY TEXT HERE']

しかし、(sc.addFileの代わりに)-filesオプションを使用してコマンドラインからファイル(readme.txt)を渡そうとすると、失敗します。以下のように。

実行2:spark_distro.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)
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)))

external_package.py上記と同じ

スパーク送信

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および--file同じ目的で使用されますか?誰かがあなたの考えを共有できますか?.

11
goks

私はついに問題を理解しました、そしてそれは確かに非常に微妙な 1つです。

疑われるように、2つのオプション(sc.addFile--files)は等しくないであり、これは(確かに非常に微妙に)示唆されていますドキュメントで(強調を追加):

addFile(path、recursive = False)
このSparkジョブをすべてのノードでダウンロードするファイルを追加します。

--filesファイル
エグゼキュータの作業ディレクトリに配置されるファイルのコンマ区切りリスト。

平易な英語では、sc.addFileで追加されたファイルはエグゼキュータとドライバの両方で使用できますが、--filesで追加されたファイルはエグゼキュータでのみ使用できます。したがって、(OPの場合のように)ドライバーからそれらにアクセスしようとすると、No such file or directoryエラーが発生します。

これを確認しましょう(OP内の無関係な--py-filesおよび1000のものをすべて削除します):

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へのアクセスを要求するのはdriverプログラムです。スクリプトを変更して、executorstest_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.02.2.0の両方でテスト済み。

[〜#〜] update [〜#〜](コメントの後):私のfs.defaultFS設定もHDFSを指しているようです:

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

しかし、ここで(つまり、木ではなく)森に焦点を当て、この議論全体が学術的な関心のみである理由を説明しましょう

ファイルの受け渡し処理対象--filesフラグを付けるのは悪い習慣です。後から考えると、オンラインでほとんど使用されていない参照を見つけることができた理由がわかりました。おそらく実際には誰も使用しておらず、正当な理由があります。

(私が--py-filesについて話しているのではないことに注意してください。これは、別の正当な役割を果たします。)

Sparkは分散処理フレームワークであり、クラスターと分散ファイルシステム(HDFS)上で実行されるため、最善の方法は、すべてのファイルをすでにHDFSに処理することです--- 期間。ファイルが処理される「自然な」場所SparkはHDFSであり、ローカルではありませんFS-いくつかありますがtoyローカルFSをデモンストレーション目的でのみ使用した例。さらに、将来的に時間が必要な場合は、デプロイモードをclusterに変更すると、クラスターはデフォルトでローカルパスとファイルを認識していないことがわかります。当然のことながら...

10
desertnaut