2016-04-06 3 views
11

SparkでPythonを使用する際に問題があります。私のアプリケーションには、numpy、pandas、astropyなどのいくつかの依存関係があります。クラスタ上のノードにはHDFS以外の共通のマウントポイントやファイルシステムがないため、virtualenvを使用してすべての依存関係の環境を作成することはできません。したがって、私はspark-submit --py-filesを使用して立ち往生しています。 site-packagesの内容をZIPファイルにパッケージ化し、--py-files=dependencies.zipオプション(Easiest way to install Python dependencies on Spark executor nodes?で示唆)のようなジョブを送信します。しかし、クラスタ上のノードはまだモジュールが内部にあるようには見えず、numpyをインポートするときにはImportErrorを投げます。Sparkの--py-filesが動作しないようです。

File "/path/anonymized/module.py", line 6, in <module> 
    import numpy 
File "/tmp/pip-build-4fjFLQ/numpy/numpy/__init__.py", line 180, in <module> 
File "/tmp/pip-build-4fjFLQ/numpy/numpy/add_newdocs.py", line 13, in <module> 
File "/tmp/pip-build-4fjFLQ/numpy/numpy/lib/__init__.py", line 8, in <module> 
    # 
File "/tmp/pip-build-4fjFLQ/numpy/numpy/lib/type_check.py", line 11, in <module> 
File "/tmp/pip-build-4fjFLQ/numpy/numpy/core/__init__.py", line 14, in <module> 
ImportError: cannot import name multiarray 

私はvirtualenvのに切り替えて、ローカルpysparkシェルを使用すると、すべてが正常に動作しますので、依存関係がすべてそこにあります。誰もが知っている、何がこの問題を引き起こす可能性があり、それを修正する方法?

ありがとうございます!

+0

明らかに、問題は、Pythonが.zipファイル(。https://docs.python.org/2/library/zipimport.html)から.soモジュールをインポートできないということです。つまり、私は何とかすべてのワーカーにzipファイルを解凍して、すべてのワーカーのsys.pathにアンパック場所を追加する必要があります。私はそれを試して、それがどのように行くか見る。 –

+0

私も同様の問題があります。どのように問題を解決しましたか? – ramhiser

+0

私は、クラスタの管理者が作業者マシンに依存関係をインストールするように納得させました。もう1つの解決策は、依存関係が存在するすべてのマシンにマウントされたボリュームを作成することです。私は何か他のことができるかどうかわからない: - \ –

答えて

0

必要なすべての.pysファイルを見つけて相対的に追加することができます。 この説明のためにhereを参照してください。

import os, sys, inspect 
# realpath() will make your script run, even if you symlink it :) 
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile(inspect.currentframe()))[0])) 
if cmd_folder not in sys.path: 
    sys.path.insert(0, cmd_folder) 

# use this if you want to include modules from a subfolder 
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile(inspect.currentframe()))[0],"subfolder"))) 
if cmd_subfolder not in sys.path: 
    sys.path.insert(0, cmd_subfolder) 

# Info: 
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!! 
# __file__ fails if script is called in different ways on Windows 
# __file__ fails if someone does os.chdir() before 
# sys.argv[0] also fails because it doesn't not always contains the path 
+1

これがSparkでどのように役立ち、従業員ノードへの依存関係を取得するのか、私はよく分かりません。もう少し詳しく教えていただけますか?ありがとう! –

+0

numpyをプロジェクトにダウンロードして追加すると、そのフォルダをsysパスに追加してそこからインポートすることができます。すでにノードにnumpyがあることがわかっても、冗長性を考慮すると最適な解決策ではないかもしれませんが、ノードがあらかじめインストールされている必要はありません。 – kpie

19

まず第一に、私はあなたの依存関係がrequirements.txtに記載されていることを前提とします。パッケージとの依存関係を圧縮するには、コマンドラインで次のように実行します。

pip install -t dependencies -r requirements.txt 
cd dependencies 
zip -r ../dependencies.zip . 

の上を、cd dependenciesコマンドは、モジュールは、zipファイルのトップレベルにあることを確認することが重要です。ヘッドアップのためにDan Corin's postに感謝します。

次に、経由してジョブを送信:

spark-submit --py-files dependencies.zip spark_job.py 

--py-filesディレクティブは、Spark労働者にzipファイルを送信しますが、PYTHONPATH(私にとっては混乱の元)に追加しません。上記の溶液がビルドされませんが

An assumption that anyone doing distributed computing with commodity hardware must assume is that the underlying hardware is potentially heterogeneous. A Python egg built on a client machine will be specific to the client’s CPU architecture because of the required C compilation. Distributing an egg for a complex, compiled package like NumPy, SciPy, or pandas is a brittle solution that is likely to fail on most clusters, at least eventually.

sc.addPyFile("dependencies.zip") 

this Cloudera postからの警告:ImportErrorを修正するためにPYTHONPATHに依存関係を追加するには、スパークジョブに次の行、spark_job.pyを追加卵、同じガイドラインが適用されます。

+0

それはネイティブコードを持ち、 '.so'ファイルとして提供された依存関係でも動作しましたか?私はそれらに多くの問題があったことを覚えています。とにかく、私はチャンスを得ると、これを試してみると、それが動作する場合はそれを受け入れるだろう。 –

+0

良い質問です。 '.so'ファイルには何の問題もありませんでしたが、それは私の依存関係がDockerコンテナの内部に構築されているためです。私のSparkのワーカーもKubernetes経由でDockerのコンテナ内を走っています。これは私にある程度の同質性を与えてくれます。私はこの問題や他の問題を解決するために、[Spark + Kubernetesプロジェクト](https://github.com/ramhiser/spark-kubernetes)を開始しました。 – ramhiser

+2

私が実行しようとしていたクラスタは、私が知る限り、同質であった。主な問題は、Pythonが '.so'ファイルを動的にインポートすることを許可していないことです。ただし、Sparkは何とかそれを克服する可能性があります。私はそれを試して、あなたに戻ってきます。 –

3
  • まずあなたは基本的に、あなたのリソースが意志、 --py-ファイルまたは --files

    • あなたは上記のフラグを使用して郵便番号/ファイルを渡して、あなたのファイルを渡す必要がありますそのアプリケーションの存続期間だけHDFSで作成された一時ディレクトリに転送することができます。あなたのコードで今すぐ
  • 、JVMのように、次のコマンドを上記の、それは実行環境にファイルをロードされないものを

    sc.addPyFile("your zip/file")

    • を使用することによって、それらの郵便番号/ファイルを追加。
  • は今それを

    import zip/file as your-alias

    注を参照起動するには、次のようにエイリアスを使用してコードにあなたの郵便番号/ファイルをインポート:の.pyのように、インポート時にファイル拡張子を使用する必要はありません最後に

希望します。

+0

私はいつも '' 'ImportError:zipfile'''という名前のモジュールはありません。助言がありますか? –

+0

@ivan_bilan zipfileをzipfileの名前に置き換える必要があります。 – avrsanjay

0

また、Python zipfileモジュールで作成されたzipアーカイブの読み込みにも失敗します。 Zipアーカイブは、zipユーティリティを使用して作成する必要があります。

+1

zipfileで導入された問題は何ですか?ジップを作成する正しい方法は何ですか? – blue

+1

@blueがより具体的に更新されました – natb1

関連する問題