このエントリでは、
Databricksで動かすコードを、PyCharmなどのIDEで書きたい場合のノウハウについて示す。

Databricksへのソースコードimport/exportは、以下のエントリで記載したが、
ローカル環境とDatabricks環境で同じコードが動く訳では無いので、
以下の2つの観点で、対応する方法を考える。

  • なるべくローカルでも動くように設定する
  • 環境に依存するコードを切り替える

Databricks WorkspaceとローカルPC上のソースコードの同期方法
http://takemikami.com/2019/02/01/Databricks-WorkspacePC.html

なるべくローカルでも動くように設定する

Databricks用のコードがなるべくローカル環境でも動くように、以下をインストール・設定する。

  • Databricks Utilities
  • Apache Spark

Databricks Utilitiesのインストール

Databricks UtilitiesというDatabricks用のパッケージをインストールする。

Databricks Utilities | docs.databricks.com
https://docs.databricks.com/user-guide/dev-tools/dbutils.html

インストール方法は以下の通り。

pip install DBUtils

これをインストールし、以下のようにインポートしておくと、
PyCharmなどで「dbutils.fs.〜」のようなコードに対する警告を抑制出来る。

import DBUtils as dbutils

Apache Sparkのインストール

pysparkをローカル環境で実行出来るようにする方法は、以下エントリの通り。
ApacheSparkをダウンロード&展開し、環境変数「SPARK_HOME」を設定しておけば良い。

IntelliJ IDEAでpyspark用の開発環境を設定する手順
http://takemikami.com/2018/11/27/IntelliJ-IDEApyspark.html

インストールと環境変数を設定した上で、以下のようにインポート・初期化すると、
ローカル環境でDatabricks環境と同じように、pysparkを利用できるようになる。

from pyspark.sql import SparkSession
spark = SparkSession.builder.appName('local').getOrCreate()

環境に依存するコードを切り替える

先に記載したDBUtils、SparkSessionのインポートなどローカル環境のみで利用し、
Databricks環境にimportする時には取り除きたいコードが存在する。

この課題に対応するため、
「LOCALONLY」とコメントした行を取り除いてimportするシェルスクリプトを作る。
ついでに、「DBONLY」とコメントした行はコメントインする処理も記載する。

「databricks-cli」のインストール&初期化は以下のエントリの通り実施しておく。

Databricks WorkspaceとローカルPC上のソースコードの同期方法
http://takemikami.com/2019/02/01/Databricks-WorkspacePC.html

以下のシェルスクリプトを作成する。
※WORKSPACE_PATH, TARGET_PATH には対象パスを指定しておく。

#!/bin/sh

# configurations
WORKSPACE_PATH=※import先のPathを記載する※ 例: /Users/user@example.com/sample
TARGET_PATH=※ローカルのソースコード格納先パスを記載する※ 例: sample

SCRIPT_DIR=$(cd $(dirname $0)/.; pwd)

# make working directory
mkdir -p $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH

# upload source file to databricks
for f in `ls $SCRIPT_DIR/$TARGET_PATH`; do
  if [[ $f =~ \.py$ ]]; then
    l=PYTHON
    cat $SCRIPT_DIR/$TARGET_PATH/$f | grep -v "# *LOCALONLY" | sed "s/^# *\(.*\)# *DBONLY/\1/" > $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH/$f
  elif [[ $f =~ \.scala$ ]]; then
    l=SCALA
    cat $SCRIPT_DIR/$TARGET_PATH/$f | grep -v "// *LOCALONLY" | sed "s/^\/\/ *\(.*\)\/\/ *DBONLY/\/\1/" > $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH/$f
  elif [[ $f =~ \.r$ ]]; then
    l=R
    cat $SCRIPT_DIR/$TARGET_PATH/$f > $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH/$f
  else
    l=SQL
    cat $SCRIPT_DIR/$TARGET_PATH/$f > $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH/$f
  fi
  databricks workspace import $SCRIPT_DIR/.dbsync_tmp/$TARGET_PATH/$f $WORKSPACE_PATH/$f -l $l -o
done

# remove working directory
rm -rf $SCRIPT_DIR/.dbsync_tmp

ローカルのソースコード格納先パス配下に、以下のようなコードを置いて、
上記のシェルスクリプトを実行すると、
ローカル用コード除去とコメントインを行った上でDatabricksにインポートされる。

# COMMAND ----------

import DBUtils as dbutils  # LOCALONLY
from pyspark.sql import SparkSession  # LOCALONLY
spark = SparkSession.builder.appName('local').getOrCreate()  # LOCALONLY

# COMMAND ----------

# WORKING_PATH_PARENT = "dbfs:/tmp/sample"  # DBONLY
WORKING_PATH_PARENT = "file:///tmp/sample"  # LOCALONLY

# COMMAND ----------

# if True:  # DBONLY
if __name__ == '__main__':  # LOCALONLY
  print("sample")

具体的に上記のコードに対して、
ローカル用のコード除去とコメントインされたものは、以下のコードになる。

# COMMAND ----------



# COMMAND ----------

WORKING_PATH_PARENT = "dbfs:/tmp/sample"  

# COMMAND ----------

if True:  
  print("sample")

以上。