Open14

【dbt】notebook

YuichiYuichi

https://dk521123.hatenablog.com/entry/2024/07/20/034930

from dbt.cli.main import dbtRunner, dbtRunnerResult
import pandas as pd

# dbtRunnerを初期化
dbt = dbtRunner()

# CLIの引数をリストとして作成
cli_args = ["show", "--inline", "SELECT * FROM {{ ref('~~~') }}","--limit" ,500]

# コマンドを実行
res: dbtRunnerResult = dbt.invoke(cli_args)

# 結果をデータフレームに変換
df = pd.DataFrame([row.dict() for r in res.result for row in r.agate_table])

# データフレームを表示
display(df)

https://docs.getdbt.com/reference/commands/show

デフォルトでは、dbt showクエリ結果の最初の 5 行が表示されます。これは、表示する行数を表す--limit nフラグを渡すことでカスタマイズできます。n

YuichiYuichi

動いたやったね!

from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic)
from dbt.cli.main import dbtRunner, dbtRunnerResult
import pandas as pd

@magics_class
class DbtMagics(Magics):
    def __init__(self, shell):
        super(DbtMagics, self).__init__(shell)
        self.dbt = dbtRunner()
        self.limit = 20
        self.quiet = True

    @line_magic
    def config(self, line):
        key, value = line.split('=')
        key = key.strip()
        value = value.strip()
        if key == 'dbt.limit':
            self.limit = int(value)
        elif key == 'dbt.quiet':
            self.quiet = value.lower() == 'true'

    @cell_magic
    def dbt_show(self, line, cell):
        cli_args = ["show", "--inline", cell, "--limit", str(self.limit)]
        if self.quiet:
            cli_args.append("--quiet")
        
        res: dbtRunnerResult = self.dbt.invoke(cli_args)
        df = pd.DataFrame([row.dict() for r in res.result for row in r.agate_table])
        
        if line.strip() == 'df':
            self.shell.user_ns['df'] = df
            print("Results stored in 'df' variable")
        else:
            display(df)

    @cell_magic
    def dbt_compile(self, line, cell):
        cli_args = ["compile", "--inline", cell]
        if self.quiet:
            cli_args.append("--quiet")
        
        res: dbtRunnerResult = self.dbt.invoke(cli_args)
        compiled_sql = res.result[0].node.compiled_code
        print(compiled_sql)

# マジックコマンドを登録
ip = get_ipython()
ip.register_magics(DbtMagics)
%config dbt.limit = 20
%config dbt.quiet = false
%%dbt_show
SELECT * FROM {{ ref('~~') }}
%%dbt_compile
SELECT * FROM {{ ref('~~') }}
%%dbt_show df
SELECT * FROM {{ ref('~~') }}
df.describe()
YuichiYuichi

スクリプトの外だし

import sys
sys.path.append('/workspaces/~~/ipython')
from dbt_magics import DbtMagics
# マジックコマンドを登録
ip = get_ipython()
ip.register_magics(DbtMagics)
/workspaces/~~/ipython/dbt_magics.py
from IPython.core.magic import (Magics, magics_class, line_magic, cell_magic)
from dbt.cli.main import dbtRunner, dbtRunnerResult
import pandas as pd

@magics_class
class DbtMagics(Magics):
    def __init__(self, shell):
        super(DbtMagics, self).__init__(shell)
        self.dbt = dbtRunner()
        self.limit = 20
        self.quiet = True

    @line_magic
    def config(self, line):
        key, value = line.split('=')
        key = key.strip()
        value = value.strip()
        if key == 'dbt.limit':
            self.limit = int(value)
        elif key == 'dbt.quiet':
            self.quiet = value.lower() == 'true'

    @cell_magic
    def dbt_show(self, line, cell):
        cli_args = ["show", "--inline", cell, "--limit", str(self.limit)]
        if self.quiet:
            cli_args.append("--quiet")
        
        res: dbtRunnerResult = self.dbt.invoke(cli_args)
        df = pd.DataFrame([row.dict() for r in res.result for row in r.agate_table])
        
        if line.strip() == 'df':
            self.shell.user_ns['df'] = df
            print("Results stored in 'df' variable")
        else:
            display(df)

    @cell_magic
    def dbt_compile(self, line, cell):
        cli_args = ["compile", "--inline", cell]
        if self.quiet:
            cli_args.append("--quiet")
        
        res: dbtRunnerResult = self.dbt.invoke(cli_args)
        compiled_sql = res.result[0].node.compiled_code
        print(compiled_sql)

YuichiYuichi

よくわからんが実行しても結果が帰ってこない事象発生
dbt compileしたら復旧した

追加設定項目

dbt show -h
dbt compile -h
の項目見ながら設定項目確認していこう
これも明示的にしてもいいかも
-q, --quiet / --no-quiet Suppress all non-error logging to stdout.
Does not affect {{ print() }} macro calls.

YuichiYuichi

JupyterLab in DockerでPandasのto_clipboardを使えるようにしたった
https://zenn.dev/ds_rd/articles/pandas_clipboard

Docker上ではto_clipboardが使えないらしい

https://stackoverflow.com/questions/46547299/jupyter-server-dfdata-to-clipboard-from-remote-to-local-machine-how
pip install copydf
copyDFで解決

from copydf import copyDF  # 正しい関数名(大文字小文字に注意)

# 例: Pandas DataFrame を作成
import pandas as pd
data = {'Name': ['Alice', 'Bob', 'Charlie'], 'Age': [25, 30, 35]}
df = pd.DataFrame(data)

# データフレームをクリップボードにコピー
copyDF(df)  # 大文字小文字に注意して呼び出す
YuichiYuichi

pip install -eは、Pythonのパッケージを「編集可能モード(editable mode)」でインストールするコマンドです。これは、開発中のコードをそのまま使いたい場合に便利です。

pip install -e /path/to/myproject

pip install -eの意味

  • 編集可能モードとは、パッケージをインストールせず、指定されたディレクトリからコードを直接参照します。
  • コードを修正すると、再インストールしなくても変更が反映されます。
  • 開発中のパッケージやモジュールを試すときに便利です。

使用手順

1. パッケージのディレクトリ構造を準備

以下のようなディレクトリ構造を持つプロジェクトがあると仮定します:

myproject/
├── dbt_ipy/
│   ├── __init__.py
│   ├── dbt_ipy.py
├── setup.py
  • dbt_ipy/:モジュールのコードが含まれるディレクトリ
  • setup.py:パッケージ情報を定義するファイル

2. setup.pyを作成

編集可能モードでインストールするには、プロジェクトルートにsetup.pyを作成します。以下は簡単な例です:

from setuptools import setup, find_packages

setup(
    name='dbt_ipy',
    version='0.1.0',
    packages=find_packages(),  # パッケージを自動検出
    install_requires=[],       # 必要な依存関係を指定(今回はなし)
)

3. pip install -eを実行

プロジェクトのルートディレクトリ(setup.pyがある場所)に移動して、以下を実行します:

pip install -e .
  • .:現在のディレクトリをインストール対象に指定
  • これにより、myprojectが編集可能モードでインストールされます。

4. インストール確認

インストールされたパッケージを確認するには、以下を実行します:

pip list

出力にdbt_ipyが含まれていることを確認します。


なぜ必要か?

  • IPythonで%load_extを使うには、Pythonのインポートパス上にモジュールがある必要があります。
  • pip install -eで編集可能モードにすると、コードの修正を反映させながら簡単に利用できます。

開発時のメリット

例えば、dbt_ipy.pyを修正した場合、再度インストールしなくてもその変更が即時反映されます。これにより、開発効率が向上します。

YuichiYuichi
	"customizations": {
		"vscode": {
			"settings": {
				// jupyter notebook関連
				"notebook.lineNumbers": "on"
			},
			"extensions": [
				// jupyter notebook関連
				"ms-toolsai.jupyter"
			]
		}
	},