Tomasz Drabas, Denny Lee:入門 PySpark

いろいろ難しい Python

作成日:2020-09-20
最終更新日:

概要

副題は「Python と Jupyter で活用する Spark 2 エコシステム」。 原題は "Learning PySpark"。

感想

本書は、私には難しい。いたるところで RDD ということばが出てくる。 RDD は Resilient Distributed Datasets の頭文字語であり、 耐障害性分散データセットと訳される。 レジリエントあるいはその名詞形であるレジリエンスという概念は、 データのみならず個人や組織にまで、リスク対応能力などの意味で通用するようになっている。

Spark とは

まずそもそも、Spark のことがわからない。 Spark は、Apache Spark が正式な名称である。 訳者まえがきでは、 Spark はすっかり分散処理のフレームワークとして定着した感がありますが(後略) そもそも何を分散処理するのか、ということがわからなかった。 本書の1章では、次のように述べられている。

Apache Spark は、オープンソースの強力な分散クエリおよびデータ処理エンジンです。

これを読んで、わたしは巨大なデータベース(いわゆるビッグデータ)を扱え、 また耐障害性の高い DBMS のようなものだと理解した。 それがあっているかどうかは、よくわからない。

第2章を試してみる

わたしは PySpark を WSL の Ubuntu 20.04 にインストールした(後述)。 そして $ jupyter notebook を実行してサーバを起動し第2章を実行してみたが、いきなり sc がないと怒られた。

In [1]:sc.parallelize([('troubles', 108), ('bottles', 50000)])
Out [1]:
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-2-0475c644e3c4> in <module>
----> 1 sc.parallelize([('troubles', 108), ('bottles', 50000)])
            
NameError: name 'sc' is not defined
        

しまった。$ pyspark で起動しなければならなかった。 pp.253-254 で、同じように sc の確認からやってみる。

In [1]:sc
Out [1]:SparkContext

Spark UI

Version
v3.0.1
Master
local[*]
AppName
PySparkShell

よし、大丈夫だ。

インストール

付録 A Apache Spark のインストールの A.8 Spark のインストール (p.242) で、 Spark をインストールする方法が3種類あると説明している。

  1. ソースコードをダウンロードし、自分自身でコンパイルする。この方法が最も柔軟です。
  2. ビルド済みのバイナリをダウンロードする
  3. pip で PySpark のライブラリをインストールする(http://bit.ly/2ivVhbH)

最も柔軟です、という甘言に載せられ、私は上記の1. の通り、自分自身でコンパイルすることにした。 私の環境は、WSL Ubuntu 20.04 である。下記は 2020-09-20 に行った。

まず、Download Apache Spark™ (spark.apache.org) にアクセスする。上記のページに次のように書かれている:

  1. Choose a Spark release:(選択肢1)
  2. Choose a package type:(選択肢2)
  3. Download Spark: ダウンロードファイル名
  4. Verify this release using the バージョン番号 signatures, checksums and project release KEYS.

1. の Spark リリースの選択肢1では、 3.0.1 (Sep 02 2020 ) を選ぶ。 2. のパッケージタイプ選択肢2では、Source Code を選ぶ。 そうすると、3. のダウンロードのリンクは、 spark-3.0.1.tgz のようになっているのでこれをダウンロードする。

チェックサムを MD5 で確かめる。

$ md5sum spark-3.0.1.tgz
13ec0fbdc197e5200e469d79e8ffdacc  spark-3.0.1.tgz

一方、Apache のページには md5 のページはなく、sha512 によるチェックサムしかない。 私の環境では、sha512 は使えない。

$ sha512 spark-3.0.1.tgz
コマンド 'sha512' が見つかりません。次の方法でインストールできます:
sudo apt install hashalot

sha512 が使えるように、泥縄式ではあるが hashalot をインストールした。

$ sudo apt install hashalot

こんどは sha512 が使えるだろう。

$ sha512sum spark-3.0.1.tgz
e0f2a6da77681423c860a56ebf8eda52e5cb952cb3d636a220f43efdc6a683803e82cc022c05e4759b924ef27c14734e23c4315cff9276d14e29c23f eb7eaf35 spark-3.0.1.tgz

この値は、 https://downloads.apache.org/spark/spark-3.0.1/spark-3.0.1.tgz.sha512 から得た値と同じである。ということで大丈夫。そこでソースコードからのコンパイルを試してみた。

$ export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512M -XX:ReservedCodeCacheSize=512m"
$ export JAVA_HOME="/usr/lib/jvm/java-14-openjdk-amd64
$ ./build/mvn -Pyarn -Phadoop-2.7 -Dhadoop.version=2.7.0 -Phive -Phive-thriftserver -DskipTests clean package
(中略)
[INFO] --- scala-maven-plugin:4.3.0:testCompile (scala-test-compile-first) @ spark-core_2.12 ---
[INFO] Using incremental compilation using Mixed compile order
[INFO] Compiler bridge file: /home/username/.sbt/1.0/zinc/org.scala-sbt/org.scala-sbt-compiler-bridge_2.12-1.3.1-bin_2.12.
10__58.0-1.3.1_20191012T045515.jar
[INFO] Compiling 282 Scala sources and 27 Java sources to /mnt/c/Users/username/documents/spark/spark-3.0.1/core/target/sc
ala-2.12/test-classes ...
[ERROR] [Error] /mnt/c/Users/username/documents/spark/spark-3.0.1/core/src/test/scala/org/apache/spark/deploy/security/Had
oopDelegationTokenManagerSuite.scala:145: method reset in class UserGroupInformation cannot be accessed in object org.ap
ache.hadoop.security.UserGroupInformation
[ERROR] one error found
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Spark Project Parent POM 3.0.1:
[INFO]
[INFO] Spark Project Parent POM ........................... SUCCESS [07:37 min]
[INFO] Spark Project Tags ................................. SUCCESS [01:10 min]
[INFO] Spark Project Sketch ............................... SUCCESS [ 19.251 s]
[INFO] Spark Project Local DB ............................. SUCCESS [ 31.748 s]
[INFO] Spark Project Networking ........................... SUCCESS [ 38.369 s]
[INFO] Spark Project Shuffle Streaming Service ............ SUCCESS [ 12.073 s]
[INFO] Spark Project Unsafe ............................... SUCCESS [ 46.429 s]
[INFO] Spark Project Launcher ............................. SUCCESS [07:20 min]
[INFO] Spark Project Core ................................. FAILURE [08:18 min]
[INFO] Spark Project ML Local Library ..................... SKIPPED
[INFO] Spark Project GraphX ............................... SKIPPED
[INFO] Spark Project Streaming ............................ SKIPPED
[INFO] Spark Project Catalyst ............................. SKIPPED
[INFO] Spark Project SQL .................................. SKIPPED
[INFO] Spark Project ML Library ........................... SKIPPED
[INFO] Spark Project Tools ................................ SKIPPED
[INFO] Spark Project Hive ................................. SKIPPED
[INFO] Spark Project REPL ................................. SKIPPED
[INFO] Spark Project YARN Shuffle Service ................. SKIPPED
[INFO] Spark Project YARN ................................. SKIPPED
[INFO] Spark Project Hive Thrift Server ................... SKIPPED
[INFO] Spark Project Assembly ............................. SKIPPED
[INFO] Kafka 0.10+ Token Provider for Streaming ........... SKIPPED
[INFO] Spark Integration for Kafka 0.10 ................... SKIPPED
[INFO] Kafka 0.10+ Source for Structured Streaming ........ SKIPPED
[INFO] Spark Project Examples ............................. SKIPPED
[INFO] Spark Integration for Kafka 0.10 Assembly .......... SKIPPED
[INFO] Spark Avro ......................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  29:47 min
[INFO] Finished at: 2020-09-20T16:13:13+09:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal net.alchim31.maven:scala-maven-plugin:4.3.0:testCompile (scala-test-compile-first) on pro
ject spark-core_2.12: Execution scala-test-compile-first of goal net.alchim31.maven:scala-maven-plugin:4.3.0:testCompile
 failed.: CompileFailed -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/PluginExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn  -rf :spark-core_2.12

甘言に載せられてはいけない。ソースコードからのコンパイルはあきらめた。

ということは、ビルド済みのバイナリをダウンロードするか、 pip で PySpark のライブラリをインストールするかだ。

ほかにインストールした例がないか調べると、下記のページがみつかった。

https://phoenixnap.com/kb/install-spark-on-ubuntu

これは、ビルド済みのバイナリをダウンロードする方法のようだ。 このページにしたがってインストールしてみよう。こちらのページは、 java (opensdk)、scala、git がインストールされていることを前提としているが、 これらは私の環境では幸いすでに入っている。以下、上記にしたがって、作業をしてみた。 まず、ファイルをダウンロードする:

$ wget https://downloads.apache.org/spark/spark-3.0.1/spark-3.0.1-bin-hadoop2.7.tgz

本当は、上記のサイト直接ではなく、日本から一番近いミラーサイトからダウンロードしてくるのがよいのだが、 私の力では見つけられなかった。私の環境では、上記コマンドでダウンロードをするのに30分弱かかった。 また、spark-3.0.1 のディレクトリには、hadoop が 3.2 の版もあるが、 hadoop 2.7 のファイルを指定している。その理由は不明である。

次に、解凍したディレクトリを /opt/spark というファイルに移す。ここはよい。

そして、~/.profile に環境変数を設定するのだが、 シェルで書き込む方法と、エディタで書き込む方法の両方が示されている。 私はエディタで書き込む方法をとった。そして、~/.profile の内容を有効にするために、 $ source ~/.profile コマンドを実行する。ここまではよい。

そして、マスターを動かすために次のコマンドを実行したがエラーとなる。

$ start-master.sh
starting org.apache.spark.deploy.master.Master, logging to 
/opt/spark/logs/spark-username-org.apache.spark.deploy.master.Master-1-username-PC.out
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
failed to launch: nice -n 0 /opt/spark/bin/spark-class 
org.apache.spark.deploy.master.Master --host username-PC.localdomain --port 7077 --webui-port 8080
  nice: 優先度を設定できません: 許可がありません
full log in /opt/spark/logs/spark-username-org.apache.spark.deploy.master.Master-1-username-PC.out

許可がありません、ということはやはりこれは root で実行すべきなのだろう。

$ sudo /opt/spark/sbin/start-master.sh
starting org.apache.spark.deploy.master.Master, logging to 
/opt/spark/logs/spark-root-org.apache.spark.deploy.master.Master-1-username-PC.out
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
$

「無効な引数です」が連続して出るのは癪に障るが、エラーではないだろう。 http://127.0.0.1:8080/ にアクセスしてみた。Spark の画面が出ている。やった。 マスターの次はスレーブである。

$ start-slave.sh spark://ubuntu1:7077
starting org.apache.spark.deploy.worker.Worker, logging to 
/opt/spark/logs/spark-username-org.apache.spark.deploy.worker.Worker-1-username-PC.out
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です
sleep: 実時間の時計を読み取ることができません: 無効な引数です

私の環境では起動していない。どうやら、 spark://ubuntu1:7077 が誤りらしい。 私の環境では、URL で指定した画面は、
Spark Master at spark://username-PC.localdomain:7077
のように出ていたので、これを指定するといいだろう。

    $ start-slave.sh spark://username-PC.localdomain:7077

sleep に関する表示は相変わらず出るが、エラーではないようだ。 しかし、Spark の Web 画面には反映されない。これも、root 権限が必要ではないか。

$ sudo /opt/spark/sbin/start-slave.sh spark://username-PC.localdomain:7077

これでやっと Workers の欄に Worker Id ほかの情報が表示された。State も alive である。

さて、spark シェルは走るだろうか。

$ spark-shell
20/09/20 18:43:14 WARN Utils: Your hostname, username-PC resolves to a loopback address: 127.0.1.1; →
    using 192.168.56.1 instead (on interface eth0)
20/09/20 18:43:14 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.spark.unsafe.Platform →
    (file:/opt/spark/jars/spark-unsafe_2.12-3.0.1.jar) to constructor java.nio.DirectByteBuffer(long,int)
WARNING: Please consider reporting this to the maintainers of org.apache.spark.unsafe.Platform
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
20/09/20 18:43:15 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... →
    using builtin-java classes where applicable
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Spark context Web UI available at http://192.168.56.1:4040
Spark context available as 'sc' (master = local[*], app id = local-1600595011976).
Spark session available as 'spark'.
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 3.0.1
      /_/

Using Scala version 2.12.10 (OpenJDK 64-Bit Server VM, Java 14.0.1)
Type in expressions to have them evaluated.
Type :help for more information.
    
scala>

警告がいろいろ出ている。どうすれば直るものかわからないが、とりあえず、scala プロンプトが出た。 次は pyspark である。やっと本書の p.248 に合流できる。

$ pyspark
Python 3.8.2 (default, Jul 16 2020, 14:00:26)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
20/09/20 18:51:24 WARN Utils: Your hostname, username-PC resolves to a loopback address: 127.0.1.1; using 192.168.56.1 
instead (on interface eth0)
20/09/20 18:51:24 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.apache.spark.unsafe.Platform (file:/opt/spark/jars/spark-unsafe_2.12-3.0.1.jar)
 to constructor java.nio.DirectByteBuffer(long,int)
WARNING: Please consider reporting this to the maintainers of org.apache.spark.unsafe.Platform
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
20/09/20 18:51:26 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java 
classes where applicable
Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 3.0.1
      /_/

Using Python version 3.8.2 (default, Jul 16 2020 14:00:26)
SparkSession available as 'spark'.
>>>

その後、私の環境は WSL から WSL2 に変わったが、運よく Spark 関係はそのままインストールされていた。 現在はコマンドラインインターフェースで pyspark と入力すると、Jupyter Notebook の環境となる (ブラウザの URL が表示される)。そのときの出力はSparkContext確認画面の通りであり、  p.254 とは異なる。

誤植

p.3 の下から4行目「有行非循環グラフ(Direct Acyclic Graph = DAM)」とあるが、 「有向非循環グラフ」が正しい。

p.24 の下半分にある次のコードがある。

    
        data_2014_2 = data_from_file_conv.map(
            lambda row: (row[16], int(row[16]):)
        data_2014_2.take(5)
    

上記は誤りで、次が正しい。int row[16] のあとのカッコと take() の引数に注意。

    
        data_2014_2 = data_from_file_conv.map(
            lambda row: (row[16], int(row[16])))
        data_2014_2.take(10)
    

Python の本

書誌情報

書 名入門 PySpark
著 者Tomasz Drabas, Denny Lee
訳 者玉川 竜司
発行日2017 年 11 月 21 日 初版第1刷
発行所オライリー・ジャパン
発売元オーム社
定 価3400 円(税別)
サイズ
ISBN978-4-87311-818-2
その他越谷市南部図書室で借りて読む
NDC

まりんきょ学問所コンピュータの部屋コンピュータの本Python > Jacaueline Kazil and Katharine Jarmul:入門 PySpark


MARUYAMA Satosi