دليل Validatar

إعداد التنميط — قوالب Python

Profiling Configuration Python Templates

شرح كيفية إعداد التنميط لقوالب Python باستخدام سكربتات تعيد إطارات بيانات pandas بدلاً من تعريفات SQL منفصلة لكل مقياس.

لوحة المتابعة

نظرة عامة

تتبع قوالب مصادر البيانات القائمة على Python نهجًا مختلفًا في التنميط (profiling) عن نظيراتها المبنية على SQL. فبدلاً من تعريف تعريفات تنميط فردية بتعبيرات SQL التجميعية، تستخدم قوالب Python سكربتات تنميط — سكربتات Python كاملة تتصل بمصدر البيانات وتحسب المقاييس وتعيد النتائج كإطارات بيانات pandas.

يمنحك هذا النهج تحكمًا كاملًا في كيفية عمل التنميط لمصادر البيانات غير المبنية على SQL: يمكن تنميط واجهات API وأنظمة الملفات والتخزين السحابي والمنصات المخصصة جميعها باستخدام مكتبات Python نفسها المستخدمة في استيراد البيانات الوصفية.

تتناول هذه المقالة إعداد التنميط لقوالب فئة Script. أما القوالب المبنية على SQL، فراجع مقالة Profiling Configuration — SQL Templates.

شكل 1: نظرة عامة

تبويب Profiling — قوالب Python

افتح قالب Python وانتقل إلى تبويب Profiling. بدلًا من قائمة تعريفات التنميط، سترى سكربتات تنميط — سكربتات Python كاملة تحسب مقاييس التنميط.

كيف يختلف التنميط عبر Python عن التنميط عبر SQL

AspectSQL TemplatesPython Templates
وحدة الإعداد (Configuration unit)تعريفات تنميط فردية (واحد لكل مقياس)سكربتات تنميط (سكربت واحد يمكنه حساب عدة مقاييس)
التنفيذ (Execution)تعبيرات SQL تُنفَّذ مقابل قاعدة البياناتسكربتات Python تعمل ضمن بيئة تشغيل Python الخاصة بـ Validatar
التجميع (Batching)يجمّع Validatar تلقائيًا عدة تنميطات في استعلامات فعّالةيتحكم السكربت في كيفية حساب المقاييس وتجميعها
الوصول إلى البيانات (Data access)SQL مباشر مقابل مصدر البياناتعبر مكتبات Python (requests، pandas، عمليات إدخال/إخراج الملفات، إلخ)
المعاملات (Parameters)لا ينطبق (يستخدم SQL عناصر نائبة للجدول/العمود)معاملات القالب من تبويب Defaults متاحة
صيغة النتيجة (Result format)مُعرّفة لكل تعريف تنميطإطارات بيانات ببنية أعمدة متوقعة

سكربتات التنميط

سكربت التنميط هو برنامج Python كامل يقوم بما يلي:

  1. 1الوصول إلى معاملات القالب لتفاصيل الاتصال
  2. 2الاتصال بمصدر البيانات
  3. 3قراءة أو استعلام البيانات لحساب المقاييس
  4. 4إعادة النتائج كإطار بيانات pandas ببنية محددة

بنية المخرجات المتوقعة

ينبغي أن تعيد سكربتات التنميط إطار بيانات بأعمدة تتوافق مع بنية نتائج التنميط في Validatar:

ColumnRequiredDescription
schema_nameYesالمخطط الذي ينتمي إليه الكائن المُنمَّط
table_nameYesالجدول أو المجموعة التي يجري تنميطها
column_nameNoالعمود (فارغ في التنميطات على مستوى الجدول)
profile_keyYesالمفتاح المرجعي لتعريف التنميط (مثل record_count، null_count)
grouping_keyNoبالنسبة لتنميطات المصفوفات، بُعد التجميع
valueYesقيمة نتيجة التنميط (كسلسلة نصية)

مثال: تنميط مصدر ملفات CSV

import pandas as pd
import os

# Access template parameters
directory_path = parameters['directory_path']

results = []

# Profile each CSV file (each file is a "table")
schema_name = os.path.basename(directory_path)

for filename in os.listdir(directory_path):
    if not filename.endswith('.csv'):
        continue

    filepath = os.path.join(directory_path, filename)
    table_name = os.path.splitext(filename)[0]

    # Read the file
    df = pd.read_csv(filepath)

    # Table-level profiles
    results.append({
        'schema_name': schema_name,
        'table_name': table_name,
        'column_name': None,
        'profile_key': 'record_count',
        'grouping_key': None,
        'value': str(len(df))
    })

    results.append({
        'schema_name': schema_name,
        'table_name': table_name,
        'column_name': None,
        'profile_key': 'column_count',
        'grouping_key': None,
        'value': str(len(df.columns))
    })

    # Column-level profiles
    for col in df.columns:
        # Null count
        null_count = int(df[col].isnull().sum())
        results.append({
            'schema_name': schema_name,
            'table_name': table_name,
            'column_name': col,
            'profile_key': 'null_count',
            'grouping_key': None,
            'value': str(null_count)
        })

        # Null percent
        null_pct = round(null_count / len(df) * 100, 2) if len(df) > 0 else 0
        results.append({
            'schema_name': schema_name,
            'table_name': table_name,
            'column_name': col,
            'profile_key': 'null_percent',
            'grouping_key': None,
            'value': str(null_pct)
        })

        # Distinct count
        distinct_count = int(df[col].nunique())
        results.append({
            'schema_name': schema_name,
            'table_name': table_name,
            'column_name': col,
            'profile_key': 'distinct_count',
            'grouping_key': None,
            'value': str(distinct_count)
        })

        # Min and max for numeric columns
        if pd.api.types.is_numeric_dtype(df[col]):
            results.append({
                'schema_name': schema_name,
                'table_name': table_name,
                'column_name': col,
                'profile_key': 'min',
                'grouping_key': None,
                'value': str(df[col].min())
            })
            results.append({
                'schema_name': schema_name,
                'table_name': table_name,
                'column_name': col,
                'profile_key': 'max',
                'grouping_key': None,
                'value': str(df[col].max())
            })

profile_results = pd.DataFrame(results)

مثال: تنميط مصدر REST API

import pandas as pd
import requests

# Access template parameters
base_url = parameters['api_base_url']
api_key = parameters['api_key']

headers = {'Authorization': f'Bearer {api_key}'}

results = []

# Get list of endpoints to profile
endpoints = [
    {'schema': 'core', 'table': 'users', 'url': f'{base_url}/api/users'},
    {'schema': 'core', 'table': 'orders', 'url': f'{base_url}/api/orders'},
]

for endpoint in endpoints:
    try:
        # Get record count via API (many APIs support count endpoints)
        count_response = requests.get(
            f"{endpoint['url']}/count",
            headers=headers,
            timeout=30
        )
        if count_response.ok:
            count = count_response.json().get('count', 0)
            results.append({
                'schema_name': endpoint['schema'],
                'table_name': endpoint['table'],
                'column_name': None,
                'profile_key': 'record_count',
                'grouping_key': None,
                'value': str(count)
            })

        # Get a sample to profile fields
        sample_response = requests.get(
            f"{endpoint['url']}?limit=1000",
            headers=headers,
            timeout=60
        )
        if sample_response.ok:
            data = sample_response.json().get('data', [])
            if data:
                df = pd.DataFrame(data)

                for col in df.columns:
                    null_count = int(df[col].isnull().sum())
                    results.append({
                        'schema_name': endpoint['schema'],
                        'table_name': endpoint['table'],
                        'column_name': col,
                        'profile_key': 'null_count',
                        'grouping_key': None,
                        'value': str(null_count)
                    })

                    distinct_count = int(df[col].nunique())
                    results.append({
                        'schema_name': endpoint['schema'],
                        'table_name': endpoint['table'],
                        'column_name': col,
                        'profile_key': 'distinct_count',
                        'grouping_key': None,
                        'value': str(distinct_count)
                    })

    except requests.exceptions.RequestException:
        continue # Skip endpoints that fail

profile_results = pd.DataFrame(results)

كيف تتدفق سكربتات تنميط القالب إلى مصادر البيانات

تتبع العلاقة بين سكربتات تنميط القالب ومجموعات التنميط على مصدر البيانات نفس النمط المستخدم في قوالب SQL:

  1. 1يحدد القالب سكربتات التنميط (منطق التنميط المتاح)
  2. 2يملك مصدر البيانات مجموعات تنميط تحدد ما الذي يجب تنميطه ومتى
  3. 3تشير مجموعات التنميط إلى قدرات التنميط الخاصة بالقالب
  4. 4يستخدم التنفيذ سكربتات Python المحددة في القالب
ملاحظة

تكون سكربتات التنميط في قوالب Python أقل تفصيلًا من تعريفات تنميط SQL. غالبًا ما يحسب سكربت واحد مقاييس عديدة دفعة واحدة، بينما تملك قوالب SQL تعريفًا واحدًا لكل مقياس. لذلك قد تقدم مجموعات التنميط على مصادر البيانات التي تستخدم قوالب Python خيارات تبديل فردية أقل.

نصائح لكتابة سكربتات التنميط

معالجة البيانات الناقصة بسلاسة

قد تعيد مصادر البيانات الخارجية بيانات غير مكتملة. تحقق دائمًا من القيم الفارغة والاستجابات الفارغة وأنواع البيانات غير المتوقعة قبل حساب المقاييس:

if len(df) > 0 and col in df.columns:
    # Safe to calculate
    null_pct = round(df[col].isnull().sum() / len(df) * 100, 2)

استخدام مفاتيح تنميط متسقة

استخدم نفس مفاتيح التنميط المرجعية المستخدمة في تعريفات التنميط المبنية على SQL الجاهزة (record_count، null_count، distinct_count، إلخ). يضمن هذا عرضًا متسقًا في مستكشف البيانات (data explorer) وتوافقًا مع مجموعات بيانات الاختبار المستندة إلى التنميط.

احترام حدود معدل API

قد يتضمن التنميط عددًا كبيرًا من استدعاءات API، خاصة عند تنميط نقاط نهاية متعددة أو جلب بيانات عينة. طبِّق تحديدًا مناسبًا لمعدل الطلبات:

import time

for endpoint in endpoints:
    # ... profile the endpoint ...
    time.sleep(0.5)   # Respect rate limits

إعادة جميع القيم كسلاسل نصية

ينبغي أن يحتوي عمود value في إطار بيانات نتائج التنميط دائمًا على قيم نصية. يتعامل Validatar مع تحويل الأنواع بناءً على صيغة تعريف التنميط. استخدم str() لتحويل جميع النتائج.

تحديد نطاق التنميط بشكل مناسب

بالنسبة لمصادر البيانات الكبيرة (عدد كبير من الملفات أو نقاط نهاية API)، ضع في اعتبارك تقييد التنميط إلى مجموعة فرعية يمكن إدارتها أو أخذ عينات من البيانات بدلًا من قراءة كل سجل. يمكن لمجموعات التنميط التحكم في الكائنات التي يجري تنميطها، لكن يجب أن يكون السكربت نفسه مرنًا أمام أحجام البيانات الكبيرة.

كيف يندرج هذا ضمن الصورة الأكبر

توسّع سكربتات تنميط Python قدرات التنميط في Validatar لتشمل أي مصدر بيانات يمكن لـ Python الوصول إليه. تُخزَّن نتائج التنميط الناتجة عنها وتُعرض بشكل مطابق لنتائج التنميط المبنية على SQL — يرى المستخدمون الذين يتصفحون مستكشف البيانات أو يضبطون درجات الثقة (trust scores) نفس المقاييس بغض النظر عما إذا كانت قد نتجت عن تعبير SQL تجميعي أو سكربت Python.

لمزيد من التفاصيل حول كيفية عمل مجموعات التنميط على مستوى مصدر البيانات، راجع مقالة Profile Sets. وللاطلاع على نظرة القالب الشاملة، راجع مقالة Data Source Templates: The Complete Picture.