🚧 Under construction — VoTechWorks is being built. A free tech program — complimentary, as our commitment to get America working.
voTechWorksGrade 13 · a vocational technology learning center, by urbanicity
newSchoolWorks.com › VoTechWorks › Technology & Design › Data Management / Database Administration › ETL Pipelines: Extract, Transform, and Load for Database Administration › Lesson 2
TEC-DATA86-06 · Lesson 2 · 11 clock hours · lab

Extracting Data from Flat Files and Databases

Objective. Students will write Python scripts using the csv and psycopg2 modules to extract data from CSV files and a PostgreSQL source database into a local staging area with verified row counts.

⚠ Pending professional review

This lesson, its worked examples and its practice questions has not yet been verified by an industry-certified professional or by a certification or approval body. It is a study draft and may contain errors. Do not use it as instructions for work on a job site or on live equipment. Always follow your instructor, your supervising professional, and current official references and regulations.

VoTechWorks program approval and accreditation are still in progress. Credentials are issued only by the certifying bodies named in each program, after their own exams.

What Is Data Extraction?

Extraction is the first stage of every ETL pipeline. Its job is simple: read data from one or more source systems and move a faithful copy into a staging area without altering values. The staging area is a temporary holding zone—often a folder of flat files or a schema inside a database—where downstream transformation steps can work safely without touching the original source.

A well-written extraction script must do three things: connect to or open the source, read every row without dropping any, and verify the count before moving on. Row-count verification is not optional. If your staging file contains 9,847 rows but the source has 10,000, every transformation and load that follows will produce wrong answers silently.

Reading CSV Files with `csv.DictReader`

The Python standard library includes the `csv` module, which handles comma-separated value files reliably, including quoted fields that contain commas or newlines. The `csv.DictReader` class reads each row as a Python dictionary whose keys are the column headers from the first line of the file. This makes your code readable and independent of column order.

Basic pattern:

```python

import csv

rows = []

with open('sales.csv', newline='', encoding='utf-8') as infile:

reader = csv.DictReader(infile)

for row in reader:

rows.append(row)

print(f'Rows read: {len(rows)}')

```

Always open the file with `newline=''`—the csv module documentation requires this so that line endings inside quoted fields are handled correctly. Specify an encoding explicitly (`utf-8` is the safe default) to avoid errors on machines whose system locale differs from yours.

After reading, write the rows to a new staging CSV using `csv.DictWriter`, then compare `len(rows)` against the output file's row count. If they match, extraction is confirmed complete.

Querying a PostgreSQL Database with `psycopg2`

`psycopg2` is the standard Python adapter for PostgreSQL. It implements the DB-API 2.0 specification, which means its connection and cursor objects follow the same pattern used by other Python database drivers.

Connection pattern:

```python

import psycopg2

conn = psycopg2.connect(

host='192.168.1.10',

port=5432,

dbname='source_db',

user='etl_reader',

password='changeme'

)

cursor = conn.cursor()

cursor.execute("""

SELECT o.order_id, o.order_date, c.customer_name

FROM orders o

JOIN customers c ON o.customer_id = c.customer_id

""")

results = cursor.fetchall()

print(f'Rows fetched: {len(results)}')

cursor.close()

conn.close()

```

Use `fetchall()` for moderate result sets. For very large tables you would use `fetchmany(size)` in a loop to avoid loading millions of rows into memory at once, but for this lab the instructor-provisioned dataset is small enough for `fetchall()`.

Write results to a JSON-lines (`.jsonl`) staging file: one JSON object per line. This format is easy to parse downstream and works well with streaming readers.

Credential note: Never hard-code production passwords in a script you will share or submit. In real environments, credentials are stored in environment variables or a secrets manager. For this lab, use the credentials your instructor provides on the lab sheet only.

Calling a REST API with `requests`

Many modern data sources expose a REST API that returns JSON. The `requests` library (install with `pip install requests`) makes HTTP calls straightforward.

```python

import requests

response = requests.get('https://example.com/api/employees')

print(f'HTTP status: {response.status_code}')

data = response.json() # parse JSON body

print(f'Records received: {len(data)}')

```

Always check `response.status_code`. A `200` means success. Codes in the `4xx` range indicate a client error (wrong URL, missing authentication); codes in the `5xx` range indicate a server error. Log the status code before doing anything else—if it is not `200`, raise an exception or exit gracefully rather than writing empty or partial data to the staging area.

Append the parsed records to your staging area using `json.dumps()` per line in a `.jsonl` file.

Verifying Row Counts

Every extraction step must end with a printed log line that states the source name and the number of rows read. Compare that number to the instructor answer key. A mismatch of even one row is a failing extraction. This discipline carries directly into professional practice: data engineers and DBAs are accountable for data completeness from the moment they touch a source.

Safety and Professional Practice

Data extraction touches real or realistic databases. Observe these rules during all lab work:

Key terms10

ETLExtract, Transform, Load — a three-stage process for moving data from source systems into a target store such as a data warehouse or staging database.
Staging areaA temporary storage location (flat files, schema, or database) that holds extracted data before transformation and loading steps are applied.
csv.DictReaderA class in Python's standard csv module that reads each row of a CSV file as an ordered dictionary, using the header row as keys.
psycopg2The most widely used Python database adapter for PostgreSQL; it follows the DB-API 2.0 specification and allows Python scripts to execute SQL and retrieve results.
JSON Lines (JSONL)A text file format in which each line is a valid, self-contained JSON object; commonly used in data pipelines because it is easy to append to and parse incrementally.
HTTP status codeA three-digit number returned by a web server indicating the result of an HTTP request; 200 means success, 4xx indicates a client error, and 5xx indicates a server error.
Row-count verificationA data quality check that compares the number of records read from the source against the number written to the staging area to confirm no rows were lost during extraction.
fetchall()A DB-API cursor method that retrieves all remaining rows from a query result set and returns them as a list of tuples.
REST APIRepresentational State Transfer Application Programming Interface — a web service design style that uses standard HTTP methods (GET, POST, etc.) to expose data, typically returned as JSON.
DB-API 2.0A Python Enhancement Proposal (PEP 249) that defines a standard interface for database adapters, ensuring that code using psycopg2 or similar drivers follows consistent patterns for connections, cursors, and queries.
In class: Use the csv.DictReader class to extract a 10,000-row CSV sales file, print a row count, and write the raw rows to a new staging CSV; compare input and output row counts to confirm completeness. · Connect to an instructor-provisioned PostgreSQL source database with psycopg2, execute a SELECT query against two joined tables, fetch all results, and write them to a JSON-lines staging file. · Call a public JSON REST API endpoint (instructor-specified, returning sample employee or product data) using the Python requests library, parse the response, and append records to the same staging area, logging the HTTP status code and record count.
Materials: Student laptops, Python 3 (standard library + pip), psycopg2 library, requests library, PostgreSQL 15 source database (instructor VM), sample CSV and API endpoint provided by instructor, PostgreSQL documentation (postgresql.org)
Check: Lab submission: working Python scripts plus a plain-text log showing correct row counts for all three sources; pass = scripts execute without unhandled exceptions and all row counts match instructor answer key within 0 rows

Practice check8

Answer each question, then check it. Nothing is recorded; this is your own practice.

ETL pipeline development / Python scripting
1. You open a CSV file with `csv.DictReader` and collect all rows into a list. The list contains 9,950 items, but the instructor answer key says the source has 10,000 rows. What is the most likely cause?
PostgreSQL / psycopg2 database connectivity
2. Which psycopg2 method should you call to retrieve the complete result set of a SELECT query as a list of tuples when the result set is small enough to fit in memory?
ETL pipeline development / REST API consumption
3. After calling `requests.get(url)`, what should your script do before attempting to parse the response body as JSON?
Database administration / data governance and security
4. A classmate's extraction script connects to the PostgreSQL source database and issues the following statement: `DELETE FROM orders WHERE order_date < '2020-01-01';`. Why is this a serious problem?
ETL pipeline design / data management concepts (DAMA CDMP)
5. What is the primary purpose of a staging area in an ETL pipeline?
ETL pipeline development / data storage formats
6. You need to store extracted query results in a format where each record is a self-contained JSON object on its own line, making the file easy to append to and parse incrementally. Which format should you choose?
PostgreSQL / Python database programming
7. You are writing a psycopg2 script and want to ensure the database connection is always closed even if an exception is raised during the query. Which Python construct is most appropriate?
DAMA CDMP — Data Quality
8. In the context of the DAMA data management framework, row-count verification after extraction is an example of which discipline?
Record this lesson on my transcript. Sign in with your key and enrollment email to record lessons (enroll free if you have no key). This page stays open to read and practise.