Python Programming for AI and ML

Chapter 8
Data Access, Persistence and Integration

Post Graduate Program in AI and ML
Python Programming for AI and ML   •   Post Graduate

8. Data Access, Persistence and Integration

Introduction and Context

Artificial intelligence and machine-learning systems rarely operate on data created inside a single Python script. Training data may arrive as CSV files, transaction records may be stored in SQL databases, configuration may be represented as JSON, documents may be collected through web APIs, and trained models may be persisted in binary or columnar formats. The quality of an AI/ML solution therefore depends not only on algorithms but also on how reliably data is acquired, interpreted, validated, stored, transformed, and traced.

Data access is the process of reading information from files, databases, services, or other systems. Persistence refers to retaining data or program objects beyond the lifetime of a running process. Integration connects heterogeneous sources and allows them to participate in a coherent analytical workflow. These activities introduce technical questions—such as encoding, schema compatibility, transaction management, and performance—as well as governance questions involving privacy, security, ownership, and provenance.

Python provides a rich ecosystem for these tasks: built-in file operations and regular expressions; the `csv`, `json`, and `sqlite3` modules; libraries such as `pandas`, `requests`, `SQLAlchemy`, `pyarrow`, and `joblib`; and serialization formats such as JSON, Pickle, Parquet, and relational tables. The professional programmer must select among them deliberately rather than treating formats as interchangeable.

Learning Objectives

After studying this chapter, the learner should be able to:

1. Explain the purposes and trade-offs of text, CSV, JSON, binary, and columnar formats.

2. Read and write files safely using Python context managers and appropriate encodings.

3. Apply regular expressions to controlled extraction and validation tasks.

4. Design reliable interactions with SQL databases and web APIs.

5. Distinguish serialization, persistence, interchange, and executable object storage.

6. Validate schemas, handle missing and malformed data, and preserve data provenance.

7. Identify privacy, security, governance, and reproducibility risks in data pipelines.

8. Select appropriate integration approaches for AI/ML applications.

A Data Lifecycle for Python Applications

A useful mental model is a data lifecycle consisting of acquisition, inspection, validation, transformation, persistence, use, and retention or deletion. Each stage should make its assumptions explicit. For example, a data-loading function should specify whether dates are parsed, whether duplicate records are permitted, which fields are mandatory, and how errors are reported.

A robust workflow separates raw data from cleaned data. Raw inputs should normally be retained in an immutable or append-only location, while transformed outputs receive a new version or identifier. This separation permits reprocessing when a cleaning rule changes and supports auditability. It also prevents a common failure: overwriting the only copy of the original data with an irreversible transformation.

Data contracts are agreements between producers and consumers concerning field names, types, units, valid ranges, nullability, and update frequency. In machine learning, a data contract may also specify the meaning of a label and the time at which each feature became available. Without such agreements, a technically successful pipeline can produce semantically invalid training data or cause training-serving skew.

Text Files, Encodings and Regular Expressions

Plain text is the simplest persistence format and remains important for logs, prompts, source documents, and configuration fragments. Python should generally open text files with an explicit encoding and a context manager:

```python

from pathlib import Path

path = Path("events.log")

with path.open("r", encoding="utf-8") as stream:

for line in stream:

print(line.rstrip())

```

The context manager closes the file even when an exception occurs. `Path` objects provide clearer, platform-independent path handling than manually concatenated strings. For large files, iteration avoids loading the complete file into memory. Binary files should be opened with modes such as `rb` and `wb`; decoding should occur only when the byte representation is known.

Encoding is a mapping between characters and bytes. UTF-8 is a widely used default, but a file’s actual encoding should not be guessed casually. Replacing undecodable characters can silently corrupt identifiers or labels. A pipeline should instead record decoding errors, quarantine problematic records, or apply an explicitly justified recovery rule.

Regular expressions are compact languages for describing text patterns. In Python, the `re` module supports searching, matching, grouping, substitution, and splitting. Raw strings reduce confusion caused by backslashes:

```python

import re

pattern = re.compile(r"^[A-Z]{2}-\d{4}$")

valid = bool(pattern.fullmatch("AB-2048"))

```

`fullmatch` is appropriate when the entire value must conform to a rule; `search` is suitable when a pattern may occur within a larger string. Regular expressions are useful for extracting identifiers, validating controlled formats, and cleaning predictable text. They are not a substitute for a parser when the input has nested structure, quoting rules, or a formal grammar. Poorly designed expressions can also cause excessive backtracking and denial-of-service risks. Restricting input length and using simple, tested patterns are prudent safeguards.

Structured Files: CSV and JSON

CSV is a tabular interchange format, but it is less simple than its appearance suggests. Fields may contain commas, quotation marks, newlines, or missing values. The Python `csv` module handles these conventions more safely than splitting lines manually:

```python

import csv

with open("customers.csv", newline="", encoding="utf-8") as file:

reader = csv.DictReader(file)

for row in reader:

customer_id = row["customer_id"]

```

A CSV file normally does not preserve rich data types. Dates, Boolean values, and numerical values are commonly represented as strings and must be converted under an explicit schema. Column names should be checked, unexpected columns reported, and duplicate headers rejected or handled deliberately. For large analytical files, `pandas.read_csv` provides parsing, chunking, type inference, and missing-value handling, but automatic inference should be inspected rather than trusted blindly.

JSON represents objects, arrays, strings, numbers, Booleans, and null values. It is well suited to nested records, API responses, and configuration. The standard library offers `json.load` and `json.dump` for files and `json.loads` and `json.dumps` for strings:

```python

import json

with open("config.json", encoding="utf-8") as file:

config = json.load(file)

with open("config.normalized.json", "w", encoding="utf-8") as file:

json.dump(config, file, indent=2, sort_keys=True)

```

JSON is human-readable and language-independent, but it can be verbose and does not natively express every domain type. Dates, decimal precision, and binary values require conventions. A JSON document should be validated against a schema when it is exchanged between systems. Validation may check required properties, types, allowed values, and constraints such as minimum length. Parsing is not validation: syntactically correct JSON may still violate application rules.

Binary and Columnar Persistence

Binary formats store data as bytes rather than as directly readable characters. They can reduce size and improve speed, but portability, version compatibility, and security require careful attention. Python’s Pickle can serialize many Python objects:

```python

import pickle

with open("model.pkl", "wb") as file:

pickle.dump(model, file)

```

Pickle must never be loaded from an untrusted source because deserialization can execute arbitrary code. It is therefore appropriate only in controlled environments with trusted artifacts, access controls, integrity checks, and compatible Python dependencies. For portable model exchange, formats such as ONNX or a framework-specific safe format may be preferable. Simple numerical arrays may be stored with NumPy formats, while Arrow-based formats support language-neutral data interchange.

Columnar formats, especially Parquet, store values by column rather than by row. This arrangement is advantageous for analytical queries that select a subset of columns, because irrelevant columns can be skipped. Columnar compression often performs well when adjacent values have similar types or patterns. Parquet also stores schema information and can represent nested structures. It is generally more suitable than CSV for large analytical datasets, although it is not automatically the best choice for frequent single-record updates.

A format decision should consider readability, schema support, compression, query pattern, interoperability, append and update behavior, and trust boundary. CSV is convenient for simple exchange; JSON is useful for nested messages; a relational database supports constraints and transactions; Parquet is effective for analytical storage; and trusted binary formats can efficiently preserve complex in-process objects.

Relational Databases and SQL Integration

A relational database represents data in tables connected by keys and manipulated through SQL. Its strengths include constraints, indexes, transactions, concurrency control, and durable storage. Python’s `sqlite3` module is suitable for local applications and teaching, while PostgreSQL, MySQL, and other systems are commonly accessed through database drivers or SQLAlchemy.

Parameterized queries are essential. Values must not be concatenated into SQL strings:

```python

import sqlite3

connection = sqlite3.connect("sales.db")

try:

connection.execute(

"INSERT INTO sales(customer_id, amount) VALUES (?, ?)",

(customer_id, amount)

)

connection.commit()

except Exception:

connection.rollback()

raise

finally:

connection.close()

```

Parameterization prevents SQL injection and also handles quoting and data types correctly. A database design should identify primary keys, foreign keys, uniqueness rules, nullability, and indexes. Indexes accelerate reads but impose storage and write costs. Normalization reduces update anomalies, whereas denormalization may improve read performance in carefully designed analytical systems.

Transactions group operations into an atomic unit. The familiar ACID properties—atomicity, consistency, isolation, and durability—describe desirable transaction behavior. In a machine-learning pipeline, a transaction can prevent a partially loaded batch from appearing as complete. Bulk insertion, batching, connection pooling, and query planning become important as data volume grows. Object-relational mappers improve developer productivity but do not remove the need to understand generated SQL and database constraints.

When extracting training data, the query itself is part of the experiment. It should be versioned with feature definitions, filters, time windows, and label construction logic. Time-aware extraction is particularly important: using information that was unavailable at prediction time creates leakage and produces misleading evaluation results.

Web APIs and External Services

Web APIs provide programmatic access to remote data or capabilities. A reliable client must account for authentication, timeouts, status codes, pagination, rate limits, retries, response schemas, and service changes. A minimal request should not wait forever:

```python

import requests

response = requests.get(

"https://api.example.org/items",

params={"page": 1},

timeout=10

)

response.raise_for_status()

payload = response.json()

```

API keys and tokens should be held in a secret manager or environment configuration, not committed to source control. HTTPS protects data in transit, but certificate verification should not be disabled merely to bypass a configuration problem. Retry logic should distinguish transient failures, such as temporary unavailability, from permanent failures, such as invalid authentication. Exponential backoff with a maximum retry count helps avoid overwhelming a service. Retried writes require idempotency considerations; otherwise the same transaction may be performed twice.

Pagination must be implemented according to the provider’s contract. A client should record request time, endpoint, parameters, response status, and source version where permitted. Caching can reduce cost and improve reproducibility, but cached data requires an expiry policy and should not expose personal information improperly.

Validation, Provenance and Reproducible Integration

Validation operates at several levels. Syntactic validation checks whether a file or message can be parsed. Structural validation checks fields and types. Semantic validation checks whether values make sense—for example, an age cannot be negative and a transaction currency must belong to an approved set. Statistical validation detects unexpected distributions, duplicate rates, missingness, or sudden changes. No single validation layer is sufficient.

A useful ingestion result distinguishes accepted records, rejected records, and records requiring review. Rejection should include a reason and, where privacy policy permits, a reference to the source record. Silent coercion—such as converting an invalid date to a null value—can conceal serious defects.

Data provenance records where data came from, when it was obtained, which code and parameters transformed it, and which output artifacts were produced. A provenance record may include source URI, extraction timestamp, file checksum, schema version, software environment, query identifier, and transformation version. Hashes help detect changes, but they do not prove that a source is truthful. Lineage is particularly important for regulated decisions and scientific reproducibility.

Idempotency is the property that repeating an operation produces the same logical result. It can be achieved through stable record identifiers, upserts, checkpoints, and deduplication keys. Exactly-once behavior is difficult across distributed systems; practical designs often combine at-least-once delivery with idempotent processing.

Security, Privacy and Governance

Data integration expands the attack surface. Risks include malicious files, SQL injection, credential leakage, unsafe deserialization, insecure temporary files, over-privileged database accounts, and accidental exposure through logs. The principle of least privilege means that a process receives only the permissions required for its task. Secrets should be rotated, access should be audited, and sensitive values should be masked in logs.

Privacy protection begins with purpose limitation and data minimization. A pipeline should collect only data necessary for a defined use, retain it for an appropriate period, and restrict access according to role. Direct identifiers and quasi-identifiers require careful treatment; pseudonymization reduces exposure but does not automatically make data anonymous. Encryption at rest and in transit, controlled deletion, consent or other lawful bases, and documented retention policies may be required by organizational policy or applicable law.

AI/ML systems add risks of label misuse, re-identification, memorization, and biased sampling. Governance should document data ownership, permitted use, known limitations, human oversight, and procedures for correcting records. The provenance of a feature is not merely a technical detail: it affects whether a model’s output can be explained and defended.

An Illustrative Case: Integrating Retail Transactions for Demand Forecasting

Background. A fictional retailer wants to forecast daily product demand. Sales transactions are stored in a PostgreSQL database, product metadata arrive as CSV files from suppliers, and public holiday information is obtained from a web API.

Situation and problem. Initial forecasts appear accurate in development but fail after deployment. Investigation reveals inconsistent product identifiers, duplicated supplier rows, missing time zones, and a holiday API that occasionally returns incomplete pages. The training query also includes a price correction entered after the sales date.

Analysis. The team maps each source to a data contract. Product identifiers are normalized through a governed mapping table rather than fuzzy matching without review. Supplier files are loaded into a raw zone with checks for required columns, duplicate keys, numeric ranges, and encoding errors. The API client records page tokens, timestamps, status codes, and response hashes. The database query is rewritten so that only information available before the forecast cutoff is included.

Approach. Transactions are extracted in time-partitioned batches using parameterized SQL and checkpoint identifiers. Validated records are written to Parquet with a schema version and source metadata. Rejected records enter a quarantine table. A feature-building job joins sales, products, and holidays using effective dates. The final dataset is generated by a versioned pipeline, and a statistical monitoring task compares missingness and category distributions with the training baseline.

Outcome. The resulting forecasts are less vulnerable to leakage and more reproducible. When the holiday provider changes its response format, schema validation raises an alert instead of silently producing incomplete features. The organization can trace a forecast dataset back to source files, queries, API responses, and code versions.

Learning points. Integration quality depends on semantic alignment, not merely successful file reads. Time is a data dimension, validation must be explicit, and provenance makes both debugging and governance possible.

Common Errors and Professional Practices

Frequent mistakes include reading an entire large file unnecessarily, relying on automatic type inference, splitting CSV lines with `str.split`, using `eval` or unsafe deserialization, constructing SQL through string concatenation, omitting API timeouts, retrying non-idempotent writes blindly, logging secrets, and overwriting raw data. Another error is treating a checksum as a complete provenance record or assuming that a syntactically valid document is trustworthy.

Professional practice favors explicit encodings and schemas, context managers, parameterized queries, bounded retries, least privilege, immutable raw storage, versioned transformations, automated data-quality tests, and clear error categories. A pipeline should be observable: metrics for records received, accepted, rejected, latency, missingness, and schema changes are often more valuable than a single success message. Tests should include malformed inputs, duplicate records, boundary dates, authentication failures, partial API responses, and recovery after interruption.

Current Developments

Modern data platforms increasingly use open table and columnar ecosystems based on Apache Arrow and Parquet, enabling data exchange across Python, SQL engines, and distributed processing systems. Data contracts are becoming machine-readable and are often enforced in continuous integration. Feature stores and metadata catalogs support reuse and lineage, while data-observability tools monitor freshness, volume, distribution, and schema drift.

Streaming systems introduce additional concerns such as event time, late-arriving data, replay, watermarking, and exactly-once claims. Privacy-enhancing methods—including differential privacy, secure enclaves, and federated learning—seek to reduce exposure, although each involves utility, complexity, and governance trade-offs. Generative AI applications also increase the importance of provenance for retrieved documents, prompt data, and model-generated content.

Chapter Summary

Reliable AI/ML applications depend on disciplined data access, persistence, and integration. Text files require careful encoding and safe resource handling; CSV and JSON require schema-aware parsing; binary formats require trust and compatibility controls; and columnar formats support efficient analytical workloads. SQL databases provide durable, constrained, transactional storage, while web APIs demand timeouts, authentication, pagination, retry, and provenance mechanisms. Validation must address syntax, structure, semantics, and statistical behavior. Versioned raw data, idempotent processing, data contracts, and lineage improve reproducibility. Security and privacy require least privilege, secret protection, safe deserialization, data minimization, and accountable governance. The appropriate format or integration method is determined by the data’s structure, access pattern, trust boundary, scale, and organizational obligations.

Key Terms

Encoding: A rule that maps characters to bytes.

Regular expression: A pattern language used to search, extract, or validate text.

CSV: A delimited tabular text format with conventions for quoting and fields.

JSON: A structured, language-independent format for objects, arrays, and primitive values.

Serialization: Converting an object or data structure into a storable or transferable representation.

Deserialization: Reconstructing data or an object from a serialized representation.

Columnar format: A storage format that organizes values by columns for analytical efficiency.

Schema: A formal description of fields, data types, constraints, and relationships.

Data contract: An agreement defining expectations between data producers and consumers.

Parameterized query: An SQL statement in which values are supplied separately from the query text.

Transaction: A group of database operations treated as a logical unit.

ACID: Atomicity, consistency, isolation, and durability properties of reliable transactions.

API: An interface through which software accesses functions or data provided by another system.

Idempotency: The property that repeating an operation produces the same logical result.

Data provenance: Recorded information about a dataset’s origin, transformations, and usage.

Data lineage: The trace of relationships from source data through processing to outputs.

Schema drift: An unintended change in fields, types, or structure over time.

Data leakage: Use of information in model development that would not be available at prediction time.

Least privilege: Granting only the access permissions necessary for a task.

Quarantine: Isolating rejected or suspicious records for investigation rather than discarding them silently.

Review Questions

Short Answer Questions

1. Why should Python file operations normally use a context manager?

2. Distinguish syntactic validation from semantic validation.

3. Why is Pickle unsafe for untrusted input?

4. What is the purpose of parameterized SQL queries?

5. Define data provenance and name two items it may record.

Long Answer Questions

1. Compare CSV, JSON, Parquet, and relational databases for an AI/ML data pipeline.

2. Explain how transactions, constraints, indexes, and parameterized queries contribute to reliable database integration.

3. Describe a robust Python client for a paginated web API, including authentication, timeouts, retries, and provenance.

4. Discuss the role of data contracts and schema validation in preventing training-serving skew.

5. Explain the principal privacy and security risks involved in data persistence and integration and propose controls.

Analytical / Application Questions

1. A pipeline reads supplier CSV files whose columns and encodings vary monthly. Design an ingestion and quarantine strategy that preserves raw data and detects structural and semantic errors.

2. A model’s offline accuracy is high, but production performance falls after a pricing-system update. Use the concepts of provenance, time-aware extraction, schema drift, and leakage to diagnose the problem.

3. Select suitable formats and storage mechanisms for a system containing API messages, large historical features, frequently updated customer records, and trusted model artifacts. Justify each choice.

22. Multiple Choice Questions with Answers

Question 1

A Python program must validate that an identifier consists of exactly two uppercase letters, a hyphen, and four digits. Which approach is most appropriate?

A. Use `re.fullmatch` with a pattern such as `r"[A-Z]{2}-\d{4}"`

B. Split the identifier on every character and compare string lengths only

C. Use `eval` to interpret the identifier as Python code

D. Search for any digit using `re.search`

Correct Answer: A. Use `re.fullmatch` with a pattern such as `r"[A-Z]{2}-\d{4}"`

Question 2

Why should a CSV file normally be read with Python’s `csv` module rather than by splitting each line on commas?

A. The `csv` module automatically encrypts the file

B. It correctly handles quoting, embedded commas, and related CSV conventions

C. It converts every field into a validated database record

D. It guarantees that all values have correct semantic types

Correct Answer: B. It correctly handles quoting, embedded commas, and related CSV conventions

Question 3

Which property makes Parquet particularly suitable for analytical queries that use only a few columns from a large dataset?

A. It stores all values as human-readable text

B. It requires a separate database server for every query

C. Its columnar organization permits irrelevant columns to be skipped

D. It supports unrestricted execution of serialized Python objects

Correct Answer: C. Its columnar organization permits irrelevant columns to be skipped

Question 4

Which practice most directly prevents SQL injection when inserting a user-provided value?

A. Concatenating the value into the SQL string after removing spaces

B. Using a parameterized SQL statement and supplying the value separately

C. Writing the value into a CSV file before constructing SQL

D. Encoding the value with Base64 and concatenating it

Correct Answer: B. Using a parameterized SQL statement and supplying the value separately

Question 5

Why is loading a Pickle file from an untrusted source dangerous?

A. Pickle can execute arbitrary code during deserialization

B. Pickle cannot represent numerical values

C. Pickle always deletes the original file

D. Pickle stores data only in plain text

Correct Answer: A. Pickle can execute arbitrary code during deserialization

Question 6

An API client repeatedly retries a request that creates a new payment. What is the principal risk?

A. The response will always be returned in CSV format

B. The API will automatically convert the payment to a database schema

C. The same payment may be created more than once if the operation is not idempotent

D. HTTPS will disable authentication after the first request

Correct Answer: C. The same payment may be created more than once if the operation is not idempotent

Question 7

Which item is an example of semantic rather than syntactic validation?

A. Checking whether a JSON document has a closing brace

B. Checking whether a required field exists

C. Checking whether an age value is not negative

D. Checking whether a CSV file can be opened

Correct Answer: C. Checking whether an age value is not negative

Question 8

A training query uses a price correction entered two weeks after the sales date to predict demand on the original date. What problem does this create?

A. Columnar compression

B. Data leakage caused by using information unavailable at prediction time

C. Safe transaction isolation

D. Character encoding

Correct Answer: B. Data leakage caused by using information unavailable at prediction time

Question 9

Which design best supports reproducible reprocessing after a cleaning rule changes?

A. Overwrite raw files with cleaned values

B. Keep immutable raw inputs and version transformed outputs and code

C. Delete rejected records immediately

D. Store only the latest API response without timestamps

Correct Answer: B. Keep immutable raw inputs and version transformed outputs and code

Question 10

Which control best reflects the principle of least privilege?

A. Give every pipeline component administrator access

B. Place database passwords in source code for convenience

C. Grant a loader only the tables and operations required for its task

D. Disable audit logs to reduce storage costs

Correct Answer: C. Grant a loader only the tables and operations required for its task

Python Programming for AI and ML
Chapter 8 of 15