Python と pyodbc を Azure Databricks に接続する

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

下記の指示に従って、pyodbc をインストールして構成し、使用します。

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

注意

Databricks には、pyodbc の代替として、Databricks SQL Connector for Python が用意されています。 Databricks SQL Connector for Python は、設定と使用がより簡単で、pyodbc よりも堅牢な一連のコーディング構造を備えています。 ただし、10 MB を超えるクエリ結果をフェッチするときのパフォーマンスは、pyodbc の方が高い場合があります。

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

要件

  • 以下のいずれかを実行しているローカルの開発マシン。
    • macOS
    • Windows
    • .rpm または .deb ファイルをサポートしている Unix または Linux ディストリビューション
  • pip
  • Unix、Linux、または macOS の場合は Homebrew
  • Azure Databricks クラスター、Databricks SQL ウェアハウス、またはその両方。 詳しくは、「コンピューティング構成リファレンス」と「SQL ウェアハウスとは」をご覧ください。

手順 1: ソフトウェアのダウンロード、インストール、構成

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

  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: 構成をテストする

この手順では、Azure Databricks クラスターまたは Databricks SQL ウェアハウスを使って、samples カタログの nyctrips スキーマ内の trips テーブルに対してクエリを実行し、結果を表示する Python コードを作成して実行します。

  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 名を使用する代わりに、接続設定をインラインで指定することもできます。 次の例は、Azure 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)

次の例では、Azure Databricks の個人用アクセス トークンの代わりに、OAuth ユーザーツーマシン (U2M) 認証または OAuth 2.0 ブラウザー ベースの認証を使用しています。 この例では、前述の環境変数 DATABRICKS_SERVER_HOSTNAMEDATABRICKS_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_HOSTNAMEDATABRICKS_HTTP_PATH、および次の環境変数が既に設定されていることを前提としています。

  • サービス プリンシパルの [アプリケーション (クライアント) ID] 値に ARM_CLIENT_ID を設定します。
  • サービス プリンシパルの OAuth シークレットの [シークレット] 値に DATABRICKS_OAUTH_SECRET を設定します。 (Microsoft Entra ID シークレットは、Databricks ODBC ドライバーを使用した OAuth M2M 認証または OAuth 2.0 クライアント資格情報認証ではサポートされていません。)

詳細については、「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('ARM_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 を使用する場合の一般的な問題を扱います。

Unicode のデコード エラー

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

<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

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

解決策: お使いの pyodbc のインストールをバージョン 4.0.32 以上にアップグレードします。

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

GitHub の mkleehammer/pyodbc リポジトリで「イシュー」を参照してください。