Pandas & NumPy Academy · Lekcja

Łączenie z bazą danych za pomocą SQLAlchemy

Utwórz silnik SQLAlchemy dla SQLite i PostgreSQL, a następnie przekaż go do pd.read_sql, aby wczytać tabelę do DataFrame.

Lekcja 1 z 413 kroki

Łączenie z bazą danych za pomocą SQLAlchemy to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Pandas & NumPy Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Dlaczego łączyć Pandas z bazami danych?

Większość danych produkcyjnych znajduje się w relacyjnych bazach danych — PostgreSQL, MySQL, SQLite lub SQL Server — a nie w plikach CSV. Bezpośrednie połączenie Pandas z bazą danych umożliwia pobieranie danych do obiektu DataFrame bez wcześniejszego eksportowania ich do CSV, zapisywanie oczyszczonych obiektów DataFrame z powrotem do tabel oraz łączenie możliwości analitycznych języka Python z funkcjami indeksowania i łączenia oferowanymi przez bazę danych. Pomostem między Pandas a bazami danych jest SQLAlchemy, standardowa biblioteka abstrakcji baz danych w języku Python.

Instalowanie SQLAlchemy

SQLAlchemy to zestaw narzędzi SQL i ORM dla języka Python. Do integracji z Pandas potrzebna jest tylko warstwa Core — nie ORM. Instalację należy wykonać za pomocą pip install sqlalchemy. Potrzebny jest również sterownik konkretnej bazy danych: psycopg2 dla PostgreSQL, pymysql dla MySQL lub sqlite3 (wbudowany w Pythonie) dla SQLite. SQLAlchemy pełni funkcję warstwy abstrakcji: ten sam kod Pandas działa z każdą obsługiwaną bazą danych, jeśli zmieni się tylko ciąg połączenia.

# Install dependencies
# pip install sqlalchemy psycopg2-binary  # for PostgreSQL
# pip install sqlalchemy pymysql           # for MySQL
# sqlite3 is built into Python

import sqlalchemy as sa
import pandas as pd

print('SQLAlchemy version:', sa.__version__)

Tworzenie silnika połączenia

Pierwszym krokiem jest utworzenie silnika SQLAlchemy za pomocą adresu URL połączenia, który zawiera typ bazy danych, dane uwierzytelniające, host, port i nazwę bazy danych. Silnik jest fabryką połączeń z bazą danych — nie otwiera połączenia, dopóki nie będzie ono rzeczywiście potrzebne. Należy przekazać silnik do funkcji Pandas pd.read_sql() i df.to_sql(). Nie należy nigdy wpisywać danych uwierzytelniających bezpośrednio w kodzie; należy odczytywać je ze zmiennych środowiskowych lub menedżera sekretów.

import sqlalchemy as sa
import os

# SQLite (file-based, no server needed)
sqlite_engine = sa.create_engine('sqlite:///mydata.db')

# PostgreSQL
# pg_url = 'postgresql://user:pass@localhost:5432/mydb'
# pg_engine = sa.create_engine(pg_url)

# From environment variable (safer)
# pg_engine = sa.create_engine(os.environ['DATABASE_URL'])

print(sqlite_engine)
print(type(sqlite_engine))

Odczytywanie tabeli za pomocą pd.read_sql_table()

pd.read_sql_table('table_name', con=engine) odczytuje całą tabelę bazy danych do obiektu DataFrame. Automatycznie rozpoznaje typy danych kolumn na podstawie schematu bazy danych — liczby całkowite pozostają liczbami całkowitymi, znaczniki czasu stają się obiektami datetime itd. Jest to dokładniejsze niż rozpoznawanie typów w plikach CSV. Kolumny można również ograniczyć za pomocą argumentu columns, a wiersze filtrować za pomocą schema w przypadku schematów baz danych innych niż domyślny. W przypadku bardzo dużych tabel należy zachować ostrożność: cała zawartość zostanie załadowana do pamięci RAM.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Read a full table
df = pd.read_sql_table('orders', con=engine)
print(df.shape)
print(df.dtypes)
print(df.head())

Wykonywanie zapytań za pomocą pd.read_sql_query()

pd.read_sql_query('SELECT ...', con=engine) wykonuje dowolne zapytanie SQL typu SELECT i zwraca wyniki jako obiekt DataFrame. To najbardziej elastyczne podejście: można filtrować, łączyć i agregować dane w SQL przed załadowaniem ich do Pandas, pobierając tylko potrzebne wiersze i kolumny. Zapytanie należy zapisać jako zwykły ciąg znaków języka Python. Nie należy nigdy łączyć danych wprowadzonych przez użytkownika z zapytaniami — w celu zapobiegania atakom SQL injection należy używać zapytań parametryzowanych.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

query = '''
    SELECT customer_id, SUM(amount) AS total_spent,
           COUNT(*) AS num_orders
    FROM orders
    WHERE status = 'completed'
    GROUP BY customer_id
    ORDER BY total_spent DESC
    LIMIT 100
'''

top_customers = pd.read_sql_query(query, con=engine)
print(top_customers.head())

Zapytania parametryzowane dla bezpieczeństwa

Nie należy nigdy budować zapytań SQL przez konkatenację ciągów znaków z wartościami podanymi przez użytkownika — otwiera to drogę do luk umożliwiających ataki SQL injection. Zamiast tego należy używać zapytań parametryzowanych: parametry należy przekazywać jako słownik z nazwanymi symbolami zastępczymi. SQLAlchemy obsługuje ich poprawne maskowanie. Składnia symboli zastępczych to :name w zapytaniach tekstowych SQLAlchemy lub %(name)s w zapytaniach w stylu psycopg2. Parametryzacji należy używać zawsze, nawet w skryptach wewnętrznych, aby wyrobić sobie dobre nawyki.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Safe: parameterised query
params = {'status': 'completed', 'min_amount': 500.0}
query = sa.text(
    'SELECT * FROM orders WHERE status = :status AND amount > :min_amount'
)

with engine.connect() as conn:
    df = pd.read_sql_query(query, con=conn, params=params)
print(f'Loaded {len(df)} rows')

Obsługa dużych wyników zapytań partiami

W przypadku dużych wyników zapytań należy użyć parametru chunksize w funkcji pd.read_sql_query(), aby otrzymać iterator obiektów DataFrame zamiast ładować wszystko naraz. Działa to podobnie jak pd.read_csv(chunksize=...), ale pobiera wiersze z bazy danych partiami. W połączeniu ze wzorcem akumulatora narastającego umożliwia agregowanie wyników zapytań zwracających miliony wierszy bez wyczerpywania pamięci RAM.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('postgresql://user:pass@host/db')

total = 0.0
count = 0

for chunk in pd.read_sql_query(
    'SELECT amount FROM orders',
    con=engine,
    chunksize=50000
):
    total += chunk['amount'].sum()
    count += len(chunk)

print(f'Mean amount: {total/count:.2f}')

Menedżery kontekstu połączeń

Połączenia z bazą danych należy zawsze otwierać wewnątrz menedżera kontekstu (with engine.connect() as conn:), aby mieć pewność, że połączenie zostanie prawidłowo zamknięte nawet w przypadku wystąpienia wyjątku. Brak zamykania połączeń prowadzi w środowisku produkcyjnym do wyczerpania puli połączeń, przez co nowe zapytania mogą zawisnąć w oczekiwaniu na wolne miejsce. Pula połączeń SQLAlchemy zarządza stałą liczbą połączeń i automatycznie wykorzystuje je ponownie, gdy używane są menedżery kontekstu.

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')

# Using context manager — connection always closed properly
with engine.connect() as conn:
    df = pd.read_sql_query(
        'SELECT * FROM products WHERE category = "Electronics"',
        con=conn
    )
    print(f'Products loaded: {len(df)}')
# Connection is automatically returned to the pool here

Sprawdzanie schematu bazy danych

Przed napisaniem zapytań trzeba wiedzieć, jakie tabele i kolumny istnieją. Funkcja Inspector biblioteki SQLAlchemy umożliwia odczytanie schematu bazy danych bez pisania surowego kodu SQL. inspector.get_table_names() wyświetla listę wszystkich tabel, a inspector.get_columns('table') zwraca nazwy i typy kolumn. Jest to przydatne podczas pracy z nieznanymi bazami danych i czytelniejsze niż ręczne uruchamianie poleceń PRAGMA table_info() lub \d tablename.

import sqlalchemy as sa

engine = sa.create_engine('sqlite:///sales.db')
inspector = sa.inspect(engine)

# List all tables
tables = inspector.get_table_names()
print('Tables:', tables)

# Get columns for the 'orders' table
for col in inspector.get_columns('orders'):
    print(f'  {col["name"]}: {col["type"]}')

Zamykanie silników i dobre praktyki

W długo działających skryptach lub aplikacjach internetowych po zakończeniu pracy należy wywołać engine.dispose(), aby zamknąć wszystkie połączenia w puli. W przypadku krótkich skryptów sprzątaniem zajmuje się moduł garbage collectora języka Python. Dobre praktyki dotyczące połączeń z bazą danych w potokach danych: utworzyć silnik raz na początku skryptu i używać go ponownie, korzystać z domyślnych ustawień puli połączeń (pool_size=5) oraz włączyć pool_pre_ping=True, aby automatycznie ponownie nawiązywać połączenie, jeśli serwer bazy danych uruchomi się ponownie między zapytaniami.

import sqlalchemy as sa

# Production-grade engine creation
engine = sa.create_engine(
    'postgresql://user:pass@host:5432/mydb',
    pool_size=5,          # max 5 persistent connections
    max_overflow=10,      # allow 10 temporary extra connections
    pool_pre_ping=True,   # verify connection before use
    connect_args={'connect_timeout': 10}
)

# ... run all your queries ...

# At the end of the application/script
engine.dispose()
print('Engine disposed')

Porównanie szybkości read_sql i read_csv

W przypadku danych znajdujących się już w bazie danych z odpowiednimi indeksami pd.read_sql_query z filtrowanym zapytaniem jest często szybsze niż eksportowanie danych do CSV i jego odczyt. Serwer bazy danych stosuje filtry przed wysłaniem danych, ograniczając transfer sieciowy i narzut związany z analizowaniem danych. W przypadku bardzo szerokich tabel baza danych może również zwrócić tylko potrzebne kolumny. Jednak odczyt z oddalonej bazy danych przez wolną sieć może być wolniejszy niż odczyt lokalnego pliku Parquet — należy zawsze zmierzyć wydajność obu rozwiązań w konkretnym środowisku.

import pandas as pd
import sqlalchemy as sa
import time

engine = sa.create_engine('sqlite:///data.db')

# Database read with server-side filter
start = time.time()
df_sql = pd.read_sql_query(
    'SELECT * FROM transactions WHERE amount > 100 AND year = 2024',
    con=engine
)
print(f'SQL read: {time.time()-start:.3f}s, {len(df_sql):,} rows')

Szybkie sprawdzenie

Proszę sprawdzić swoją znajomość zagadnień analizy danych z tej lekcji.

Podsumowanie lekcji

W tej lekcji nauczyli się Państwo, że: sa.create_engine() tworzy wielokrotnego użytku fabrykę połączeń na podstawie ciągu URL, pd.read_sql_query() wykonuje dowolne zapytania SQL i zwraca obiekt DataFrame, a zapytania parametryzowane z sa.text() i params zapobiegają lukom umożliwiającym ataki SQL injection. W następnej części przyjrzymy się wykonywaniu bardziej złożonych zapytań SQL z poziomu Pandas oraz łączeniu SQL z logiką języka Python.

Bezpłatny start

Ucz się Python dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
30
Lekcje
120

Często zadawane pytania

Czy lekcja „Łączenie z bazą danych za pomocą SQLAlchemy” jest bezpłatna?

Tak — pełny tekst „Łączenie z bazą danych za pomocą SQLAlchemy” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Pandas & NumPy Academy, przejdź na CoddyKit PRO. Kurs Pandas & NumPy Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Łączenie z bazą danych za pomocą SQLAlchemy”?

Utwórz silnik SQLAlchemy dla SQLite i PostgreSQL, a następnie przekaż go do pd.read_sql, aby wczytać tabelę do DataFrame. Ćwiczysz Pandas & NumPy Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Pandas & NumPy Academy?

Nie wymagamy żadnego doświadczenia. Pandas & NumPy Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Łączenie z bazą danych za pomocą SQLAlchemy”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Pandas & NumPy Academy?

Tak. Każda lekcja Pandas & NumPy Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Łączenie z bazą danych za pomocą SQLAlchemy
  2. Wykonywanie zapytań SQL z Pandas
  3. Zapisywanie obiektów DataFrame w tabelach bazy danych
  4. Pandas a SQL: wybór odpowiedniego narzędzia
← Powrót do Pandas & NumPy Academy