Sterownik języka Microsoft Python dla programu SQL Server — mssql-python

mssql-python to sterownik języka Python firmy Microsoft dla programu SQL Server, usługi Azure SQL Database, usługi Azure SQL Managed Instance oraz bazy danych SQL w usłudze Microsoft Fabric. Korzysta z Direct Database Connectivity (DDBC), więc możesz się łączyć bez konieczności instalowania zewnętrznego menedżera sterowników. Sterownik obsługuje Python 3.10 lub nowszy i jest zgodny ze specyfikacją Python Database API 2.0, jednocześnie dodając usprawnienia przyjazne Python do codziennego rozwoju.

Wybieranie punktu początkowego

Plan bazowy produkcji dla Azure SQL

Ten przykład łączy się z Azure SQL za pomocą zarządzanej tożsamości oraz szyfrowania Tabular Data Stream (TDS) 8.0. Odczytuje ustawienia połączenia ze zmiennych środowiskowych i ustawia oddzielne limity czasu logowania i wykonywania zapytań. Każda ponowna próba wywołuje ponownie connect(), zamiast używać obiektu połączenia, które zakończyło się niepowodzeniem. Menedżery kontekstu zwalniają połączenie i kursor po każdej próbie.

Używaj tego pomocnika tylko do idempotentnych zapytań odczytu, które można powtarzać. Nie używaj go do ponownego wykonywania pojedynczych zapisów lub częściowo ukończonych transakcji.

Słowa kluczowe ConnectRetryCount i ConnectRetryInterval w parametrach połączenia włączają w SQL Server funkcję odporności nieaktywnego połączenia: sterownik automatycznie ponownie nawiązuje zerwane nieaktywne połączenie. To różni się od mechanizmu ponawiania na poziomie aplikacji w tym przykładzie, który ponawia zapytanie, gdy kończy się ono niepowodzeniem z powodu błędu przejściowego, takiego jak zakleszczenie lub przekroczenie limitu czasu zapytania. Te dwie rzeczy się uzupełniają, więc zachowaj oba.

Sprawdzenie błędu Azure odpowiada standardowemu angielskiemu komunikatowi o błędzie 40501, nawet gdy diagnostyka pomija numer błędu. Sprawdza ddbc_error także znane numery, gdy są obecne. Dopasowanie odbywa się w miarę możliwości: wiadomości zlokalizowane lub inaczej sformatowane mogą się nie zgadzać. Więcej informacji można znaleźć w artykule Przejściowe błędy połączenia.

import logging
import os
import re
import time

import mssql_python

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)s %(name)s %(message)s",
)
logger = logging.getLogger("app")

TRANSIENT_DRIVER_ERRORS = frozenset({
    "Timeout expired",
    "Connection timeout expired",
    "Client unable to establish connection",
    "Communication link failure",
    "Connection failure during transaction",
    "Serialization failure",
    "Statement completion unknown",
})

AZURE_THROTTLING_ERRORS = frozenset({
    40197, 40501, 40540, 40613, 40680, 49918, 49919, 49920, 10928, 10929,
})

_ERROR_NUMBER_RE = re.compile(r"\b(?:Error|Msg)\s+(\d+)\b")
_AZURE_40501_MESSAGE = "The service is currently busy. Retry the request after 10 seconds."


def is_azure_throttling(error: BaseException) -> bool:
    """Best-effort detection of Azure SQL throttling in ProgrammingError text."""
    if not isinstance(error, mssql_python.ProgrammingError):
        return False
    ddbc_text = getattr(error, "ddbc_error", "") or ""
    return (
        _AZURE_40501_MESSAGE in ddbc_text
        or any(int(m) in AZURE_THROTTLING_ERRORS for m in _ERROR_NUMBER_RE.findall(ddbc_text))
    )


def query_with_retry(
    conn_str: str,
    sql: str,
    *params,
    max_attempts: int = 3,
    login_timeout_s: int = 5,
    query_timeout_s: int = 10,
) -> list:
    """Fetch an idempotent read query, reconnecting before each retry."""
    for attempt in range(1, max_attempts + 1):
        try:
            with mssql_python.connect(conn_str, timeout=login_timeout_s) as conn:
                conn.timeout = query_timeout_s
                with conn.cursor() as cursor:
                    cursor.execute(sql, *params)
                    rows = cursor.fetchall()
            logger.info("query succeeded on attempt %d/%d", attempt, max_attempts)
            return rows
        except mssql_python.Error as exc:
            azure_throttling = is_azure_throttling(exc)
            transient = (
                isinstance(exc, mssql_python.OperationalError)
                and exc.driver_error in TRANSIENT_DRIVER_ERRORS
            )
            if not (transient or azure_throttling) or attempt == max_attempts:
                logger.error("query failed on attempt %d/%d: %s", attempt, max_attempts, exc.driver_error)
                raise
            delay = (10 if azure_throttling else 1) * (2 ** (attempt - 1))
            logger.warning(
                "query attempt %d/%d hit transient error %r; retrying in %ds",
                attempt, max_attempts, exc.driver_error, delay,
            )
            time.sleep(delay)
    raise ValueError("max_attempts must be at least 1")


def main() -> None:
    # Read configuration from the environment; never hard-code secrets.
    server = os.environ["SQL_SERVER"]      # for example, <server>.database.windows.net
    database = os.environ["SQL_DATABASE"]  # for example, AdventureWorks
    client_id = os.getenv("AZURE_CLIENT_ID")  # set for a user-assigned managed identity

    # Authenticate with the workload's managed identity over TDS 8.0 encryption.
    # ConnectRetryCount/ConnectRetryInterval transparently reconnect a dropped
    # idle connection; they don't replay a failed query.
    conn_str = (
        f"Server={server};"
        f"Database={database};"
        "Authentication=ActiveDirectoryMsi;"
        "Encrypt=strict;"
        "ConnectRetryCount=3;"
        "ConnectRetryInterval=10;"
        # Parallel dials to all resolved IPs; safe on single-IP targets.
        "MultiSubnetFailover=Yes;"
    )
    if client_id:
        conn_str += f"UID={client_id};"

    query = """
        SELECT TOP 10
            p.BusinessEntityID,
            p.FirstName,
            p.LastName
        FROM Person.Person AS p
        ORDER BY p.BusinessEntityID;
    """

    try:
        rows = query_with_retry(conn_str, query)
        for business_entity_id, first_name, last_name in rows:
            print(f"{business_entity_id}\t{first_name}\t{last_name}")
    except mssql_python.Error:
        logger.exception("query failed")
        raise


if __name__ == "__main__":
    main()

Bardziej szczegółowe wskazówki dotyczące każdego z omówionych tu zagadnień można znaleźć w sekcjach uwierzytelnianie Microsoft Entra, buforowanie połączeń, szyfrowanie i certyfikaty, logika ponawiania oraz obsługa błędów.

Kluczowe funkcje

Wprowadzenie

Artykuł Opis
Installation Zainstaluj mssql-python i sprawdź swoje środowisko Pythona.
Szybki start: Połącz się z mssql-python Połącz się z lokalną lub testową instancją SQL Server i uruchom pierwsze zapytanie.
Szybki start: Połącz się z Jupyter Notebook Używaj mssql-python w notatniku do interaktywnej eksploracji danych.
Szybki start: Kopia masowa Przenieś duże zbiory danych do SQL Server za pomocą API kopiowania masowego.
Szybki start: Szybkie prototypowanie Szybko buduj małe skrypty i dowody koncepcji.
Szybki start: Powtarzalne wdrożenia Pakuj, konfiguruj i dostarczaj aplikacje Python, które komunikują się z SQL.
Szybki start z Apache Arrow Pobieraj wyniki zapytań jako tabele Apache Arrow na potrzeby analitycznych przepływów pracy.

Konfiguruj i uwierzytelniaj

Artykuł Opis
dostawca mssql-odbc (Wersja zapoznawcza) Wybierz natywnego dostawcę wersji zapoznawczej i przejrzyj obsługiwane funkcje oraz znane problemy.
Parametry połączenia Składnia łańcuchów połączeń, popularne słowa kluczowe i przykłady.
Buduj łańcuchy połączeń programatycznie Bezpiecznie twórz ciągi połączeń na podstawie konfiguracji i sekretów.
Zarządzanie połączeniami Otwieraj, ponownie używaj i zamykaj połączenia w sposób czysty.
Buforowanie połączeń Strojenie basenu, czas użytkowania i wzorce ponownego użycia.
Szyfrowanie i certyfikaty Tryby szyfrowania TLS, walidacja certyfikatów oraz TDS 8.0.
Uwierzytelnianie Microsoft Entra Uwierzytelnianie bez hasła dla usługi Azure SQL z użyciem tożsamości zarządzanej, jednostki usługi oraz przepływów interaktywnych i kodu urządzenia.
Najlepsze rozwiązania dotyczące zabezpieczeń Parametryzacja, zarządzanie sekretami, zasada najmniejszych uprawnień i szyfrowanie.
Grupy dostępności Połącz się z grupami dostępności Always On i replikami tylko do odczytu.

Praca z danymi

Artykuł Opis
Wykonywanie zapytań execute, executemany, partie wieloinstrukcyjne oraz zbiory wyników.
Pobieranie danych fetchone, fetchmany, fetchall, oraz wzorce strumieniowe.
Zapytania sparametryzowane Bezpiecznie wiąż parametry, aby zapobiec wstrzyknięciu SQL.
Procedury składowane Wywołuj procedury, odczytuj parametry wyjściowe i zestawy wyników procesów.
Zarządzanie kursorem Czas życia kursora, przewijanie i dostrajanie parametru arraysize.
Obiekty wierszowe Uzyskuj dostęp do wierszy według indeksu, nazwy lub jako mapowań.
Zarządzanie transakcjami Zatwierdzanie, wycofanie, punkty zapisu i poziomy izolacji.
Dzielenie na strony Wzorce paginacji opartej na kluczach i paginacji z przesunięciem dla dużych zbiorów wyników.
Obsługa błędów mssql_python.Error, DatabaseError, oraz strukturę błędów SQL Server.
Logika ponowień Wykrywaj błędy przejściowe i ponawiaj próby z wykładniczo wydłużanymi odstępami.

Typy danych i funkcje SQL Server

Artykuł Opis
Mapowania typów danych Tabela i reguły konwersji typu SQL Server-to-Python.
Obsługa daty i godziny datetime, datetime2, datetimeoffset oraz kwestie związane ze strefami czasowymi.
Typy danych dziesiętnych i walutowych Dokładne typy liczbowe i precyzja decimal.Decimal.
Dane ciągowe i Unicode varchar, nvarchar, sortowania i strony kodowe.
Obsługa NULL Logika trójwartościowa, strażnicy i pandas interoperacyjni.
Dane binarne varbinary, image, oraz strumieniowanie dużych obiektów.
Konwertery niestandardowe typu Rejestruj konwertery wejściowe i wyjściowe dla typów niestandardowych.
Operacje kopiowania masowego Wysokowydajne wstawianie danych za pomocą interfejsu API kopiowania zbiorczego.
Dane JSON Przechowuj, zapytuj i niszcz JSON z pomocą FOR JSON i OPENJSON.
Dane XML Pracuj z typem xml danych, XPath i XQuery.
Dane przestrzenne typy geometry oraz geography w Pythonie.
Kolumny rozrzedłe Rzadkie kolumny i zestawy kolumn dla szerokich tabel.
Odnajdywanie schematów Przeglądaj bazy danych, tabele, kolumny i indeksy.

Integruj się z narzędziami i frameworkami Python

Artykuł Opis
Integracja z Apache Arrow Pobieraj wyniki jako tabele Arrow do analizy bez kopiowania danych.
Integracja Pandas Załaduj wyniki zapytań do DataFrames i zapisuj je z powrotem.
Integracja z Polars Używaj Polars z mssql-python do obciążeń kolumnowych.
Integracja z DuckDB Zapytuj dane SQL Server obok lokalnych tabel DuckDB.
Integracja z FastAPI Zintegruj mssql-python z usługami FastAPI.
Testuj i wdrażaj aplikacje FastAPI Konfiguruj pulowanie, błędy, uwierzytelnianie, testy i ustawienia wdrożenia dla usług FastAPI.
Integracja z Flask Używaj mssql-python w aplikacjach Flask.
Wzorce asynchroniczne Połącz mssql-python z asyncio oraz pulami wątków.
Dostęp do danych i wzorce analityczne Wybierz właściwą ścieżkę odczytu dla dostępu do kursora, ekstrakcji strzałek, pandas, polars oraz analityki DuckDB na danych SQL.
Wzorce ładowania i ruchu danych Wybierz odpowiednią ścieżkę zapisu dla wstawiania wierszy, kopiowania zbiorczego, operacji upsert MERGE, ładowania obiektów DataFrame oraz importu plików CSV.

Wdrażanie i obsługa

Artykuł Opis
Tworzenie kontenerów i lokalne tworzenie Skonfiguruj kontenery Docker, devcontainery i potoki CI dla aplikacji Python łączących się z SQL.
Dostrajanie wydajności Dostrajanie puli połączeń, przygotowane instrukcje, rozmiary partii i kopiowanie zbiorcze.
Troubleshooting Znajdź wskazówki według objawu lub komunikatu o błędzie.
Instalacja i rozwiązywanie problemów z połączeniami Rozwiązuj problemy z instalacją, połączeniami, kontenerami i CI.
Rozwiązywanie problemów z zapytaniami, danymi i operacjami Rozwiązuj problemy z zapytaniami, typem danych, wydajnością, transakcjami i kopiowaniem masowym.
Konfiguracja modułu Ustawienia na poziomie modułu, logowanie hooków i flagi funkcji.

Migracja do mssql-python

Artykuł Opis
Przejdź z pyodbc Mapuj interfejsy API pyodbc i parametry połączenia do mssql-python.
Migracja z pymssql Zamień pymssql na mssql-python, zachowując zachowanie.
Migracja z SQLite Przenieś lokalne obciążenia SQLite do SQL Server lub Azure SQL.
Migrowanie z bazy danych PostgreSQL Kompleksowy przewodnik dla programistów Python przechodzących z PostgreSQL na SQL Server z mssql-python.

Prośba o funkcję

Aby zażądać funkcji, otwórz problem w repozytorium mssql-python GitHub.