Równoległe pobieranie stron z użyciem asyncio, httpx i BeautifulSoup.
import asyncio
import httpx
from bs4 import BeautifulSoup
class AsyncScraper:
def __init__(self, urls):
self.urls = urls
async def fetch(self, client, url):
try:
r = await client.get(url, timeout=10.0, follow_redirects=True)
if r.status_code == 200:
soup = BeautifulSoup(r.text, 'html.parser')
return {"url": url, "title": soup.title.string.strip() if soup.title else ""}
except Exception as e:
return {"url": url, "error": str(e)}
async def run(self):
async with httpx.AsyncClient() as client:
return await asyncio.gather(*[self.fetch(client, u) for u in self.urls])
Kiedy używać
Użyj tego wzorca, gdy musisz pobrać dane z wielu adresów URL naraz, a pobieranie ich po kolei zajmowałoby zbyt dużo czasu.
Typowe pułapki
Brak limitu równoległych połączeń może przeciążyć docelowy serwer lub Twoje własne łącze — warto dodać semafor ograniczający liczbę jednoczesnych żądań.
2. Python: Dekorator Retry z Backoffem
Python
Automatyczne ponawianie awaryjnych zapytań sieciowych z opóźnieniem.
import time
from functools import wraps
def retry(retries=3, delay=2):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
attempts = 0
while attempts < retries:
try:
return func(*args, **kwargs)
except Exception as e:
attempts += 1
if attempts == retries: raise e
time.sleep(delay)
return wrapper
return decorator
Kiedy używać
Stosuj przy komunikacji z zewnętrznymi API lub bazami danych, gdzie chwilowe błędy sieciowe są normą.
Typowe pułapki
Stały czas oczekiwania między próbami bywa nieoptymalny — w produkcji lepiej sprawdza się backoff wykładniczy (exponential backoff) zamiast stałego opóźnienia.
3. Python: Weryfikacja Tokenów JWT
Python
Bezpieczne dekodowanie i walidacja nagłówków autoryzacyjnych (PyJWT).
import jwt
import os
# UWAGA: nigdy nie zapisuj sekretu na stałe w kodzie.
# Wczytaj go ze zmiennej środowiskowej.
SECRET_KEY = os.environ["JWT_SECRET_KEY"]
ALGORITHM = "HS256"
def verify_token(token: str):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return {"valid": True, "payload": payload}
except jwt.ExpiredSignatureError:
return {"valid": False, "error": "Token wygasł"}
except jwt.InvalidTokenError:
return {"valid": False, "error": "Nieprawidłowy token"}
Kiedy używać
Niezbędne w każdym API, które uwierzytelnia użytkowników tokenami — sprawdza ważność i integralność danych przed ich użyciem.
Typowe pułapki
Nigdy nie trzymaj klucza sekretnego w kodzie źródłowym — zawsze wczytuj go ze zmiennych środowiskowych, jak w przykładzie powyżej.
4. Python: Sanitizacja Danych Wejściowych
Python
Ochrona przed XSS i wstrzykiwaniem kodu przy użyciu html.escape.
import html
def sanitize_input(user_input):
if not isinstance(user_input, str):
return ""
return html.escape(user_input.strip())
Kiedy używać
Konieczne wszędzie tam, gdzie dane od użytkownika trafiają później do HTML-a — np. komentarze, formularze, opisy profili.
Typowe pułapki
Sama sanitizacja HTML nie chroni przed SQL Injection ani przed atakami na poziomie logiki aplikacji — to tylko jeden element ochrony.
5. Python: Klient Powiadomień Telegram
Python
Wysyłanie zaawansowanych raportów o statusie systemów przez API.
Przydatne do wysyłania alertów o błędach produkcyjnych, statusach zadań w tle czy raportów dziennych bezpośrednio na telefon.
Typowe pułapki
Token bota nie powinien nigdy trafić do publicznego repozytorium — przechowuj go w zmiennych środowiskowych lub secret managerze.
51. Python: Walidacja Danych z Pydantic
Python
Deklaratywna walidacja i parsowanie danych wejściowych z automatyczną konwersją typów.
from pydantic import BaseModel, EmailStr, field_validator
class UserCreate(BaseModel):
name: str
email: EmailStr
age: int
@field_validator("age")
@classmethod
def check_age(cls, v):
if v < 18:
raise ValueError("Użytkownik musi mieć co najmniej 18 lat")
return v
user = UserCreate(name="Anna", email="anna@example.com", age=25)
Kiedy używać
Stosuj przy walidacji danych z API, formularzy czy plików konfiguracyjnych — Pydantic automatycznie konwertuje typy i zwraca czytelne błędy.
Typowe pułapki
Pydantic v1 i v2 mają inną składnię walidatorów (@validator vs @field_validator) — upewnij się, którą wersję biblioteki masz zainstalowaną.
52. Python: Cache z Wygasaniem (TTL)
Python
Dekorator cache'ujący wyniki funkcji na określony czas, w przeciwieństwie do bezterminowego lru_cache.
import time
from functools import wraps
def ttl_cache(seconds=60):
def decorator(func):
cache = {}
@wraps(func)
def wrapper(*args):
now = time.time()
if args in cache and now - cache[args][1] < seconds:
return cache[args][0]
result = func(*args)
cache[args] = (result, now)
return result
return wrapper
return decorator
@ttl_cache(seconds=30)
def get_exchange_rate(currency):
# kosztowne zapytanie do zewnętrznego API
return fetch_rate(currency)
Kiedy używać
Przydatne przy danych, które zmieniają się co jakiś czas (kursy walut, ceny), gdzie standardowy lru_cache trzymałby nieaktualne dane w nieskończoność.
Typowe pułapki
Cache trzymany w zwykłym słowniku rośnie w nieskończoność, jeśli argumenty są różnorodne — w produkcji rozważ maksymalny rozmiar cache albo bibliotekę cachetools.
53. Python: Budowa CLI z argparse
Python
Tworzenie narzędzia wiersza poleceń z podkomendami i flagami.
Stosuj przy budowie własnych narzędzi deweloperskich czy skryptów administracyjnych, które mają więcej niż jedną opcję wywołania.
Typowe pułapki
Brak walidacji args.command == None (użytkownik nie podał żadnej podkomendy) spowoduje ciche niepowodzenie — dodaj obsługę tego przypadku i komunikat pomocy.
54. Python: Context Manager do Transakcji
Python
Własny context manager zapewniający commit/rollback niezależnie od tego czy wystąpił błąd.
from contextlib import contextmanager
@contextmanager
def db_transaction(connection):
try:
yield connection
connection.commit()
except Exception:
connection.rollback()
raise
finally:
connection.close()
with db_transaction(get_connection()) as conn:
conn.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1")
Kiedy używać
Przydatne wszędzie, gdzie operacja musi się zakończyć commitem albo rollbackiem, niezależnie od tego czy coś poszło nie tak w środku bloku with.
Typowe pułapki
Zapomnienie o re-raise (samo 'raise' bez argumentu) w bloku except sprawi, że błąd zniknie po cichu, a kod wywołujący nie dowie się, że transakcja się nie powiodła.
55. Python: Multiprocessing dla Zadań CPU-bound
Python
Rozdzielanie obliczeniowo ciężkich zadań na wiele rdzeni procesora.
from multiprocessing import Pool
import os
def heavy_computation(n):
return sum(i * i for i in range(n))
if __name__ == "__main__":
numbers = [10_000_000, 20_000_000, 15_000_000, 25_000_000]
with Pool(processes=os.cpu_count()) as pool:
results = pool.map(heavy_computation, numbers)
print(results)
Kiedy używać
Stosuj przy zadaniach intensywnie wykorzystujących CPU (obliczenia, przetwarzanie obrazów) — w przeciwieństwie do asyncio, które pomaga tylko przy operacjach I/O.
Typowe pułapki
Multiprocessing na Windows i w niektórych środowiskach wymaga bloku `if __name__ == '__main__':` — bez niego kod może się zapętlić przy tworzeniu procesów potomnych.
56. Python: Structured Logging (JSON)
Python
Konfiguracja loggera zwracającego wpisy w formacie JSON zamiast zwykłego tekstu.
Ułatwia analizę logów w narzędziach jak ELK czy Datadog, gdzie strukturalny JSON jest łatwiejszy do przeszukania niż zwykły tekst.
Typowe pułapki
Logowanie obiektów niezserializowalnych do JSON (np. wyjątków bez str()) spowoduje błąd w samym formatterze — zawsze konwertuj złożone obiekty na string przed przekazaniem do loggera.
Niezbędne przy testowaniu kodu integrującego się z zewnętrznymi serwisami — testy muszą być szybkie, deterministyczne i niezależne od dostępności prawdziwego API.
Typowe pułapki
Nadmierne mockowanie sprawia, że test sprawdza tylko czy funkcja wywołała mocka poprawnie, a nie czy logika biznesowa faktycznie działa — zachowaj równowagę z testami integracyjnymi.