0Pricing
Pandas & NumPy Academy · Lekcja

Parametryzowanie potoków za pomocą słowników konfiguracji

Zastąp zakodowane na stałe ścieżki plików i nazwy kolumn słownikiem konfiguracji przekazywanym w czasie działania, aby potok można było ponownie wykorzystać.

Parametryzowanie potoków za pomocą słowników konfiguracji to bezpłatna lekcja Pandas & NumPy Academy na CoddyKit. To lekcja 2 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.

Problem z wartościami wpisanymi na stałe

Potok zawierający wpisane na stałe ścieżki plików, nazwy kolumn i wartości progowe przestaje działać po zmianie środowiska — na innym serwerze, po zmianie nazwy kolumny lub zmianie reguły biznesowej. Każda zmiana wymaga edycji samego kodu potoku, co zwiększa ryzyko wprowadzenia błędów. Rozwiązaniem jest przeniesienie wszystkich zmiennych wartości do słownika konfiguracyjnego, który jest ładowany w czasie działania programu i przekazywany do funkcji potoku.

import pandas as pd

# BAD: hardcoded values scattered through code
df = pd.read_csv('/data/orders_2024.csv')
df = df.dropna(subset=['revenue', 'quantity'])
df = df[df['revenue'] < 5000]
df.to_parquet('/output/orders_clean.parquet')
print('Hardcoded paths and thresholds are fragile')

Definiowanie słownika konfiguracyjnego

Zastąp każdą wartość wpisaną na stałe wpisem w słowniku konfiguracyjnym. Grupuj powiązane ustawienia w logiczny sposób: ścieżki wejściowe i wyjściowe razem, progi czyszczenia razem, mapowania nazw kolumn razem. Słownik konfiguracyjny staje się jedynym źródłem prawdy dla wszystkich parametrów potoku. Zmiana jednej wartości w konfiguracji aktualizuje każdą funkcję, która z niej korzysta, bez modyfikowania treści funkcji.

CONFIG = {
    'input_path': '/data/orders_2024.csv',
    'output_path': '/output/orders_clean.parquet',
    'required_cols': ['order_id', 'order_date', 'revenue', 'quantity'],
    'date_cols': ['order_date'],
    'revenue_cap': 5000,
    'min_quantity': 1,
    'categorical_cols': ['region', 'category']
}
print('Config loaded:', list(CONFIG.keys()))

Przekazywanie konfiguracji do funkcji extract

Funkcja extract odczytuje wszystkie parametry z konfiguracji: ścieżkę wejściową, kolumny dat do przeanalizowania oraz ustawienia kodowania lub separatora. Oznacza to, że uruchomienie tego samego potoku dla testowego zbioru danych lub pliku z innego miesiąca wymaga tylko zmiany konfiguracji — bez zmiany kodu. Można utrzymywać osobne konfiguracje dla środowisk deweloperskich, testowych i produkcyjnych.

def extract(config):
    return pd.read_csv(
        config['input_path'],
        parse_dates=config.get('date_cols', [])
    )

df = extract(CONFIG)
print('Extracted:', df.shape)

Przekazywanie konfiguracji do funkcji transformacji

Każda funkcja transformacji otrzymuje pełną konfigurację i pobiera z niej potrzebne wartości. Funkcje powinny używać config.get('key', default) z rozsądnymi wartościami domyślnymi, aby potok był odporny na niepełne konfiguracje. Funkcja, która domyślnie wymaga progu 5000, ale pozwala zastąpić go za pomocą konfiguracji, jest jednocześnie bezpieczna i elastyczna.

def transform(df, config):
    required = config.get('required_cols', [])
    cap = config.get('revenue_cap', float('inf'))
    min_qty = config.get('min_quantity', 1)

    return (
        df
        .dropna(subset=required)
        .query(f'quantity >= {min_qty}')
        .assign(revenue=lambda d: d['quantity'] * d['unit_price'])
        .assign(revenue_capped=lambda d: d['revenue'].clip(upper=cap))
    )

df_clean = transform(df, CONFIG)
print(df_clean.shape)

Ładowanie konfiguracji z pliku JSON

W produkcyjnych potokach przechowuj konfigurację w pliku JSON zamiast w słowniku Pythona wpisanym na stałe w skrypcie. Załaduj ją za pomocą json.load() na początku działania potoku. Umożliwia to zespołom operacyjnym zmianę progów bez dostępu do kodu Pythona, a także wersjonowanie konfiguracji za pomocą Git — każda zmiana konfiguracji jest śledzonym zatwierdzeniem z opisem biznesowego powodu tej zmiany.

import json

# config.json would contain the same keys as CONFIG above
# with open('config.json') as f:
#     config = json.load(f)

# Example: write and read back
with open('/tmp/pipeline_config.json', 'w') as f:
    json.dump(CONFIG, f, indent=2)

with open('/tmp/pipeline_config.json') as f:
    loaded_config = json.load(f)

print('Loaded config from JSON:', loaded_config['revenue_cap'])

Konfiguracje zależne od środowiska

Utrzymuj osobne pliki konfiguracji dla każdego środowiska: config_dev.json, config_staging.json i config_prod.json. Określ, który plik należy załadować, na podstawie zmiennej środowiskowej. Ten wzorzec zapobiega przypadkowemu użyciu produkcyjnych ścieżek plików podczas programowania i pozwala przechowywać dane wrażliwe zależne od środowiska (takie jak dane uwierzytelniające do bazy danych) poza współdzielonym repozytorium kodu.

import os

ENV = os.environ.get('PIPELINE_ENV', 'dev')
CONFIG_PATH = f'config_{ENV}.json'

# In practice:
# with open(CONFIG_PATH) as f:
#     config = json.load(f)

print(f'Using config for environment: {ENV}')
print(f'Config file: {CONFIG_PATH}')

Zmiana nazw kolumn za pomocą konfiguracji

Dane źródłowe często mają nazwy kolumn różniące się od wewnętrznej konwencji nazewnictwa. Zamiast wpisywać na stałe df.rename(columns={'OrderDate': 'order_date', 'Qty': 'quantity'}) w treści pipeline’u, należy przechowywać mapowanie zmian nazw w konfiguracji. Dzięki temu pipeline nie zależy od nazw kolumn źródłowych i można go łatwo dostosować, gdy dostawca danych zmieni format eksportu.

CONFIG['column_rename'] = {
    'OrderDate': 'order_date',
    'Qty': 'quantity',
    'UnitPrice': 'unit_price',
    'OrderID': 'order_id'
}

def rename_columns(df, config):
    return df.rename(columns=config.get('column_rename', {}))

print('Column rename mapping stored in config.')

Konfiguracja agregacji: dynamiczne klucze groupby

Etap agregacji często grupuje dane według różnych kolumn w zależności od zastosowania. Należy przechowywać klucze grupowania i specyfikacje agregacji w konfiguracji, zamiast wpisywać je na stałe w kodzie. Dzięki temu analitycy mogą tworzyć różne tabele podsumowań (według regionu, kategorii czy miesiąca), zmieniając konfigurację bez modyfikowania funkcji agregującej. Funkcja staje się uniwersalnym agregatorem sterowanym w całości przez konfigurację.

CONFIG['agg_spec'] = {
    'group_by': ['region', 'category'],
    'agg_cols': {
        'revenue': ['sum', 'mean'],
        'quantity': ['sum', 'count']
    }
}

def aggregate(df, config):
    spec = config['agg_spec']
    return df.groupby(spec['group_by']).agg(spec['agg_cols'])

result = aggregate(df_clean, CONFIG)
print(result.head())

Walidowanie konfiguracji podczas uruchamiania

Konfigurację należy zwalidować na początku działania pipeline’u, aby wykryć brakujące lub nieprawidłowe klucze, zanim zostaną wczytane jakiekolwiek dane. Pipeline, który działa przez 10 minut, a następnie kończy się błędem, ponieważ revenue_cap jest ciągiem znaków zamiast liczbą zmiennoprzecinkową, marnuje czas. Należy sprawdzić, czy istnieją wszystkie wymagane klucze, wartości mają właściwy typ, a ścieżki są dostępne, używając krótkiej funkcji sprawdzającej konfigurację, uruchamianej przed wykonaniem kosztownych operacji wejścia-wyjścia.

def validate_config(config):
    required_keys = ['input_path', 'output_path', 'required_cols']
    for key in required_keys:
        assert key in config, f'Config missing key: {key}'
    assert isinstance(config['required_cols'], list), 'required_cols must be a list'
    assert isinstance(config.get('revenue_cap', 1), (int, float)), 'revenue_cap must be numeric'
    print('Config validation passed.')

validate_config(CONFIG)

Scalanie konfiguracji domyślnej z konfiguracją użytkownika

Należy umożliwić użytkownikom dostarczanie częściowej konfiguracji, która nadpisuje tylko interesujące ich wartości. Konfigurację użytkownika można scalić z konfiguracją domyślną za pomocą {**defaults, **user_config}. Ten wzorzec zapewnia rozsądne wartości domyślne, a jednocześnie pozostawia pełną możliwość konfiguracji. Jest to ten sam wzorzec, którego używają popularne biblioteki Pythona akceptujące konfigurację jako słownik lub argumenty słów kluczowych.

DEFAULT_CONFIG = {
    'revenue_cap': 10000,
    'min_quantity': 1,
    'date_cols': ['order_date'],
    'required_cols': ['order_id', 'revenue']
}

user_config = {'revenue_cap': 5000, 'input_path': '/data/q1.csv'}

final_config = {**DEFAULT_CONFIG, **user_config}
print('Final config revenue_cap:', final_config['revenue_cap'])  # 5000
print('Final config min_quantity:', final_config['min_quantity'])  # 1 (from default)

Zapisywanie konfiguracji razem z wynikiem

Konfigurację należy zapisać obok pliku wynikowego, aby każda osoba analizująca wynik mogła od razu odtworzyć uruchomienie pipeline’u, które go utworzyło. Należy zapisać ją jako pomocniczy plik JSON o tej samej nazwie co plik wynikowy, ale z rozszerzeniem .config.json. W zapisanej konfiguracji należy uwzględnić znacznik czasu uruchomienia pipeline’u, aby zapewnić pełną identyfikowalność każdego pliku wynikowego.

import json
from datetime import datetime

def save_with_config(df, config):
    output_path = config['output_path']
    config_path = output_path.replace('.parquet', '.config.json')

    run_metadata = {**config, 'run_at': datetime.now().isoformat()}
    with open(config_path, 'w') as f:
        json.dump(run_metadata, f, indent=2, default=str)

    df.to_parquet(output_path, index=False)
    print(f'Saved data to {output_path}')
    print(f'Saved config to {config_path}')

Szybkie sprawdzenie

Sprawdź swoją wiedzę na temat analizy danych zdobytą w tej lekcji.

Podsumowanie lekcji

W tej lekcji nauczyli się Państwo: zastępować wartości wpisane na stałe słownikiem konfiguracji wczytywanym z JSON, przekazywać konfigurację do funkcji extract, transform i aggregate w celu pełnej parametryzacji oraz walidować konfigurację podczas uruchamiania i zapisywać ją obok plików wynikowych w celu zapewnienia odtwarzalności. Następnie zajmiemy się testowaniem kroków pipeline’u za pomocą kontroli liczby wierszy i asercji ochronnych.

Często zadawane pytania

Czy lekcja „Parametryzowanie potoków za pomocą słowników konfiguracji” jest bezpłatna?

Tak — pełny tekst „Parametryzowanie potoków za pomocą słowników konfiguracji” 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 „Parametryzowanie potoków za pomocą słowników konfiguracji”?

Zastąp zakodowane na stałe ścieżki plików i nazwy kolumn słownikiem konfiguracji przekazywanym w czasie działania, aby potok można było ponownie wykorzystać. Ć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 2 z 4.

Ile czasu zajmuje lekcja „Parametryzowanie potoków za pomocą słowników konfiguracji”?

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. Strukturyzowanie etapów transformacji jako funkcji
  2. Parametryzowanie potoków za pomocą słowników konfiguracji
  3. Testowanie etapów potoku za pomocą asercji
  4. Harmonogramowanie i rejestrowanie uruchomień potoku
← Powrót do Pandas & NumPy Academy