Python と pyodbc を Databricks に接続する

ローカルの Python コードから ODBC を使用して、Databricks クラスターまたは SQLウェアハウス内のデータに接続できます。 これを行うには、オープンソースのPythonコードモジュール pyodbcを使用できます。

次の手順に従って、 pyodbcをインストール、構成、および使用します。

pyodbcの詳細については、 pyodbc Wiki を参照してください。

Databricks は、 pyodbcの代わりに Databricks SQL Connector for Python を提供しています。Python 用 Databricks SQL コネクタは、セットアップと使用が簡単で、 pyodbcよりも堅牢なコーディング構造のセットを備えています。 ただし、 pyodbc を使用すると、10 MB を超えるクエリ結果をフェッチするとパフォーマンスが向上する場合があります。

これらの手順は、 Databricks ODBC ドライバー 2.7.5、 pyodbc 5.0.1、 unixODBC 2.3.12 でテストされました。

要件

ステップ 1: ソフトウェアのダウンロード、インストール、および構成

この手順では、Databricks ODBC ドライバー、 unixodbc パッケージ、 pyodbc モジュールをダウンロードしてインストールします。 ( pyodbc モジュールには、Unix、Linux、macOSの unixodbc パッケージが必要です。 また、ODBC データソース名 (DSN) を構成して、クラスターまたは SQLウェアハウスで認証し、接続します。

  1. Databricks ODBC ドライバーをダウンロードしてインストール し、オペレーティング システムの ODBC DSN を構成し ます。

  2. Unix、Linux、およびmacOSの場合は、 unixodbc パッケージをインストールします:ターミナルからHomebrewを使用してコマンドを実行します brew install unixodbc. 詳細については、Homebrew Web サイトの「 unixodbc 」を参照してください。

  3. pyodbcモジュールをインストールします:ターミナルまたはコマンドプロンプトから、pipを使用してコマンドpip install pyodbcを実行します。詳細については、PyPI Web サイトの pyodbc と pyodbc Wiki の Install を参照してください。

ステップ 2: 構成をテストする

このステップでは、Databricks クラスターまたは Databricks SQL ウェアハウスを使用して Python コードを記述して実行し、samplesカタログのnyctripsスキーマ内のtripsテーブルをクエリーして結果を表示します。

  1. 次の内容で pyodbc-demo.py という名前のファイルを作成します。 <dsn-name> を前に作成した ODBC DSN の名前に置き換えてファイルを保存し、Python インタープリターでファイルを実行します。

    import pyodbc
    
    # Connect to the Databricks cluster by using the
    # Data Source Name (DSN) that you created earlier.
    conn = pyodbc.connect("DSN=<dsn-name>", autocommit=True)
    
    # Run a SQL query by using the preceding connection.
    cursor = conn.cursor()
    cursor.execute(f"SELECT * FROM samples.nyctaxi.trips")
    
    # Print the rows retrieved from the query.
    for row in cursor.fetchall():
      print(row)
    
  2. コードの実行を高速化するには、DSN の HTTPPath 設定に対応するクラスターを起動します。

  3. Python インタープリターで pyodbc-demo.py ファイルを実行します。 テーブルの行に関する情報が表示されます。

次のステップ

  • 別のクラスターまたは SQLウェアハウスに対して Python テスト コードを実行するには、別の DSN を作成し、 <dsn-name> を DSN の名前に変更します。

  • 別の SQL クエリーで Python テスト コードを実行するには、 execute コマンド文字列を変更します。

DSN なしの接続の使用

DSN 名を使用する代わりに、接続設定をインラインで指定することもできます。 次の例は、Databricks 個人用アクセストークン認証に DSN なしの接続文字列を使用する方法を示しています。 この例では、次の環境変数があることを前提としています。

環境変数を設定するには、ご利用になっているオペレーティングシステムのドキュメントを参照してください。

import pyodbc
import os

conn = pyodbc.connect(
  "Driver=/Library/simba/spark/lib/libsparkodbc_sb64-universal.dylib;" +
  f"Host={os.getenv('DATABRICKS_HOST')};" +
  "Port=443;" +
  f"HTTPPath={os.getenv('DATABRICKS_HTTP_PATH')};" +
  "SSL=1;" +
  "ThriftTransport=2;" +
  "AuthMech=3;" +
  "UID=token;" +
  f"PWD={os.getenv('DATABRICKS_TOKEN')}",
  autocommit = True
)

# Run a SQL query by using the preceding connection.
cursor = conn.cursor()
cursor.execute("SELECT * FROM samples.nyctaxi.trips")

# Print the rows retrieved from the query.
for row in cursor.fetchall():
  print(row)

次の例では、Databricks 個人用アクセストークンの代わりに、OAuth user-to-machine (U2M) または OAuth 2.0 ブラウザーベースの認証を使用します。 この例では、前述の DATABRICKS_SERVER_HOSTNAME 環境変数と DATABRICKS_HTTP_PATH 環境変数が既に設定されていることを前提としています。

import pyodbc
import os

conn = pyodbc.connect(
  "Driver=/Library/simba/spark/lib/libsparkodbc_sb64-universal.dylib;" +
  f"Host={os.getenv('DATABRICKS_HOST')};" +
  "Port=443;" +
  f"HTTPPath={os.getenv('DATABRICKS_HTTP_PATH')};" +
  "SSL=1;" +
  "ThriftTransport=2;" +
  "AuthMech=11;" +
  "Auth_Flow=2;" +
  "PWD=1234567",
  autocommit = True
)

# Run a SQL query by using the preceding connection.
cursor = conn.cursor()
cursor.execute("SELECT * FROM samples.nyctaxi.trips")

# Print the rows retrieved from the query.
for row in cursor.fetchall():
  print(row)

次の例では、OAuthマシン間(M2M)またはOAuth 2.0クライアント資格情報認証を使用します。 この例では、前述の DATABRICKS_SERVER_HOSTNAME 環境変数と DATABRICKS_HTTP_PATH 環境変数、および次の環境変数が既に設定されていることを前提としています。

  • DATABRICKS_CLIENT_ID をサービスプリンシパルの UUID/アプリケーション ID 値に設定します。

  • DATABRICKS_OAUTH_SECRET をサービスプリンシパルの OAuth シークレット値に設定します。

詳細については、「 OAuth マシン間 (M2M) 認証」を参照してください。

   import pyodbc
import os

conn = pyodbc.connect(
  "Driver=/Library/simba/spark/lib/libsparkodbc_sb64-universal.dylib;" +
  f"Host={os.getenv('DATABRICKS_HOST')};" +
  "Port=443;" +
  f"HTTPPath={os.getenv('DATABRICKS_HTTP_PATH')};" +
  "SSL=1;" +
  "ThriftTransport=2;" +
  "AuthMech=11;" +
  "Auth_Flow=1;" +
  f"Auth_Client_ID={os.getenv('DATABRICKS_CLIENT_ID')};" +
  f"Auth_Client_Secret={os.getenv('DATABRICKS_OAUTH_SECRET')}",
  autocommit = True
)

# Run a SQL query by using the preceding connection.
cursor = conn.cursor()
cursor.execute("SELECT * FROM samples.nyctaxi.trips")

# Print the rows retrieved from the query.
for row in cursor.fetchall():
  print(row)

トラブルシューティング

このセクションでは、Databricks で pyodbc を使用する場合の一般的な問題について説明します。

ユニコードデコードエラー

問題: 次のようなエラー メッセージが表示されます。

<class 'pyodbc.Error'> returned a result with an error set
Traceback (most recent call last):
File "/Users/user/.pyenv/versions/3.7.5/lib/python3.7/encodings/utf_16_le.py", line 16, in decode
return codecs.utf_16_le_decode(input, errors, True)
UnicodeDecodeError: 'utf-16-le' codec can't decode bytes in position 2112-2113: illegal UTF-16 surrogate

原因: バージョン 4.0.31 以下に問題が存在し pyodbc クエリーを実行すると、長い名前または長いエラー メッセージを含む列が返されるような現象が発生する可能性があります。 この問題は、新しいバージョンの pyodbcで修正されています。

ソリューション: pyodbc のインストール済み環境をバージョン 4.0.32 以降にアップグレードします。

一般的なトラブルシューティング

GitHub の mkleehammer/pyodbc リポジトリ の問題 を参照してください。