なにかしらの処理の結果、生成される複数のファイルを簡単にダウンロードできるように圧縮を行い、zipファイルへのリンクを表示するサンプルです。
サンプルノートブックはこちらです。
参考資料
ファイルの準備
ダミーデータを準備します。以下のパスは適宜変更してください。
# 処理の結果が格納されるパスです
output_file_path = "/tmp/takaaki.yayoi@databricks.com/processed"
# ブラウザからダウンロードできるようにFileStore配下のパスとします
download_file_path = "/FileStore/shared_upload/takaaki.yayoi@databricks.com/viz_results"
現在時刻を用いてフォルダを作成します。
# datetimeモジュールを使用
import datetime
t_delta = datetime.timedelta(hours=9)
JST = datetime.timezone(t_delta, 'JST')
now = datetime.datetime.now(JST)
#print(repr(now))
# YYYYMMDDhhmmss形式に書式化
directory_name = now.strftime('%Y%m%d-%H%M%S')
#print(d)
target_path = f"{output_file_path}/{directory_name}"
print("target path:", target_path)
# 日付の入ったディレクトリを作成
dbutils.fs.mkdirs(target_path)
ワインデータセットをコピーします。
dbutils.fs.cp("dbfs:/databricks-datasets/wine-quality/winequality-red.csv", target_path)
dbutils.fs.cp("dbfs:/databricks-datasets/wine-quality/winequality-white.csv", target_path)
dbutils.fs.cp("dbfs:/databricks-datasets/wine-quality/README.md", target_path)
# ファイルが格納されていることを確認
display(dbutils.fs.ls(target_path))
ファイル圧縮
DBFSの実態はオブジェクトストレージなので、ランダムアクセスが必要となるファイル圧縮をその場で行うことができません。このため、クラスターのローカルストレージに一旦コピーして圧縮を行う必要があります。
dbutils.fs
でパスを指定する際にローカルストレージを参照するには、パスの先頭にfile:
をつけます。正直ここは分かりにくいところだと思います。
こちらで触れているように、使っているAPIによってデフォルトでDBFS(分散ファイルシステム)にアクセスするのか、ローカルファイルシステムにアクセスするのかが異なります。このデフォルトの挙動を変えるためにfile:
や/dbfs
を使います。
- Spark API、
%fs
、dbutils.fs
などは、デフォルトのアクセス先はDBFSになります。 - 一方、pandasなどのシングルマシン向けPythonライブラリ(ローカルファイルシステムAPI)、
%sh
などは、デフォルトのアクセス先はローカルファイルシステムになります。
以下で使用しているshutil
ではファイルの圧縮を行いますが、上述の通り、DBFS上に直接圧縮ファイルを作成することができません。このため、DBFSからローカルファイルシステムにファイルをコピーしています。この際にdbutils.fs.cp
を使っています。これのデフォルトのアクセス先はDBFSとなるので、ここでローカルファイルシステムを参照するには、パスの先頭にfile:
を追加します。
なお、ローカルファイルシステムAPIでDBFSを参照するには、パスの先頭に/dbfs
を追加します。以下の図にまとめていますが、これでも正直分かりにくいと思います。まずは以下の2点を覚えていただくといいのではと思います。
パスのプレフィックス
- pandasでローカルファイルシステムにアクセスするにはパスはそのまま、DBFSにアクセスするにはパスの先頭に
/dbfs
を追加します。 - Spark APIや
%fs
でDBFSにアクセスするにはパスはそのまま、ローカルファイルシステムにアクセスするにはパスの先頭にfile:
を追加します。
参考資料
- Databricksファイルシステム(DBFS) - Qiita
- Databricksにおけるファイルシステム - Qiita
- Databricksを使い始めたときに感じる疑問 + ベストプラクティス - Qiita
# DBFSからローカルストレージにコピー
dbutils.fs.cp(target_path, f"file:/tmp/{directory_name}", True)
# ローカルストレージを参照
display(dbutils.fs.ls(f"file:/tmp/{directory_name}"))
shutilを使って圧縮を行います。
# ディレクトリを圧縮
import shutil
shutil.make_archive(f"/tmp/{directory_name}", format='zip', root_dir=f'/tmp/{directory_name}')
ブラウザからダウンロードできるように、DBFSの/FileStore
にファイルをコピーします。
dbutils.fs.cp(f"file:/tmp/{directory_name}.zip", f"{download_file_path}/{directory_name}.zip")
display(dbutils.fs.ls(download_file_path))
ダウンロードリンクの生成
DBFSのFileStore配下のファイルには、ブラウザから/files
のURLを指定することでアクセスすることができます。
import re
# FileStoreをfilesに置き換えます
download_url_path = re.sub("FileStore", "files", download_file_path)
print(download_url_path)
displayHTML
関数を使ってリンクをノートブック上にレンダリングします。
displayHTML (f"""
<a href='{download_url_path}/{directory_name}.zip'>{directory_name}.zip</a>
""")
このリンクをクリックするとzipファイルがローカルにダウンロードされます。これを解凍すると、上で圧縮した3つのファイルを手に入れることができます。