Python4 min read11 sections

Python for data engineering beginners: what to learn first, with runnable code

You do not need all of Python. For data engineering, a small part of it does most of the work. This guide teaches that part on a tiny CSV, one step at a time, and ends with a 10-line pipeline.

Solve “First Occurrence Map”

Free. Runs in your browser, no install.

Updated Written for: Complete beginners who know what a variable is and want to use Python for data.

What you will learn

  • Data engineers mostly use lists, dictionaries, loops, functions and the csv module, not advanced Python.
  • A CSV row read by Python is a dictionary of text. Numbers arrive as strings and must be converted.
  • Wrap risky conversions in try and except, so one bad row does not stop the whole job.
  • A pipeline is small functions chained: read, clean, filter, summarise, write.
On this page
  1. What data engineers use Python for
  2. 1. A CSV, read into Python
  3. 2. Why that matters: text is not a number
  4. 3. A function to clean one value
  5. 4. Loops and filtering
  6. 5. Summarise with a dictionary
  7. 6. A list comprehension: a loop in one line
  8. 7. Write the result back out as CSV
  9. 8. Putting it together: a 10-line pipeline
  10. Mistakes to avoid
  11. What to learn next

SQL asks a database questions. Python is how a data engineer does everything around it: reading files, cleaning messy values, calling APIs, moving data from one place to another, and running the steps on a schedule. The good news is that you only need a small slice of Python to start. This guide covers that slice on a tiny example, and every output below came from really running the code in Python.

What data engineers use Python for

  • Reading and writing files: CSV, JSON and others.
  • Cleaning data: fixing text, converting types, handling bad values.
  • Moving data: between files, databases and APIs.
  • Glue: small scripts that run steps in order and check the results.

None of that needs advanced tricks. It needs lists, dictionaries, loops, if, functions, and a few modules from the standard library.

A CSV, read into Python

Here is a small file of orders. In real life it would sit on disk, and you would open it. To keep the example runnable anywhere, the text is held in a variable and read as if it were a file. One order has a comma inside its amount, and one amount is not a number.

PythonPySpark
import csv
import io

raw = """order_id,customer,city,amount
1,Asha,Pune,"1,200"
2,Ravi,Mumbai,800
3,Meena,Chennai,n/a
4,Kiran,Pune,2500
5,Asha,Pune,300
"""

rows = list(csv.DictReader(io.StringIO(raw)))
print(len(rows), "rows")
print(rows[0])
5 rows
{'order_id': '1', 'customer': 'Asha', 'city': 'Pune', 'amount': '1,200'}

csv.DictReader turns each line into a dictionary: a set of name and value pairs, like {'customer': 'Asha'}. A list of such dictionaries is the most common shape for data in Python. Look carefully at the amount in the first row: '1,200' is in quotes. Every value from a CSV arrives as text, even the numbers.

1Read

csv.DictReader turns each line into a dictionary of text.

2Clean

clean_amount() returns a number, or None for a value like n/a.

3Filter

Keep the good rows. Count the rejected ones instead of losing them.

4Summarise

A dictionary adds up the amount per city.

5Write

csv.DictWriter saves the result.

Figure 1. The shape of almost every beginner data script: read, clean, filter, summarise, write. Each step is a small function.

Why that matters: text is not a number

Try to add 1 to an amount, the way you would with a number:

PythonPySpark
rows[1]["amount"] + 1
TypeError: can only concatenate str (not "int") to str

Python refuses, because '800' is text and 1 is a number. You must convert first, with int(). But conversion can fail too:

PythonPySpark
int(rows[0]["amount"])
ValueError: invalid literal for int() with base 10: '1,200'

The comma in 1,200 makes int() give up. And the value n/a will fail the same way. Real data is full of these, which is why cleaning is most of the work.

A function to clean one value

A function packages a piece of logic so you can reuse it and test it. This one removes commas and spaces and converts to a number. If the value cannot be converted, it returns None (Python's "no value") instead of crashing. try and except catch the failure.

PythonPySpark
def clean_amount(text):
    try:
        return int(text.replace(",", "").strip())
    except ValueError:
        return None

for sample in ["1,200", " 800 ", "n/a", "2500"]:
    print(repr(sample), "->", clean_amount(sample))
'1,200' -> 1200
' 800 ' -> 800
'n/a' -> None
'2500' -> 2500

All 4 samples behave sensibly: the good ones become numbers, and n/a becomes None. Testing a function on a few samples like this, before using it on real data, is a habit worth having from day one.

Loops and filtering

Apply the function to every row with a for loop, and keep the good rows in a new list. Bad rows go to a separate list so you can look at them later, instead of vanishing:

PythonPySpark
clean_rows = []
rejected = []

for row in rows:
    amount = clean_amount(row["amount"])
    if amount is None:
        rejected.append(row)
    else:
        clean_rows.append({"customer": row["customer"], "city": row["city"], "amount": amount})

print("kept:", len(clean_rows))
print("rejected:", len(rejected))
print(rejected[0]["customer"], "had amount", rejected[0]["amount"])
kept: 4
rejected: 1
Meena had amount n/a

4 rows were kept and one rejected, and you know which one. Never quietly throw data away: a count of rejected rows is one of the first checks a pipeline needs.

Summarise with a dictionary

To add up the amount per city, use a dictionary as a tally. get(city, 0) returns the current total, or 0 if the city has not been seen yet:

PythonPySpark
totals = {}
for row in clean_rows:
    totals[row["city"]] = totals.get(row["city"], 0) + row["amount"]

print(totals)
{'Pune': 4000, 'Mumbai': 800}

Pune has 1200 + 2500 + 300, and Mumbai has 800. Meena's Chennai order was rejected, so Chennai has no total at all. This is the same idea as GROUP BY city with SUM in SQL, which you can compare with the GROUP BY guide.

You can sort the result, largest first, with sorted and a key:

PythonPySpark
for city, total in sorted(totals.items(), key=lambda item: item[1], reverse=True):
    print(city, total)
Pune 4000
Mumbai 800

A list comprehension: a loop in one line

A list comprehension builds a list from another in one line. It is the short form of a loop that appends. Here are only the Pune amounts:

PythonPySpark
pune_amounts = [row["amount"] for row in clean_rows if row["city"] == "Pune"]
print(pune_amounts)
print(sum(pune_amounts))
[1200, 2500, 300]
4000

It reads like English: "the amount, for each row, if the city is Pune". Use it for short, simple transformations, and a normal loop when the logic needs several steps.

Write the result back out as CSV

The last step of a pipeline is to put the result somewhere. csv.DictWriter writes dictionaries as lines. Writing into a text buffer here keeps the example runnable anywhere, and in real life you would open a file instead:

PythonPySpark
out = io.StringIO()
writer = csv.DictWriter(out, fieldnames=["city", "total"], lineterminator="\n")
writer.writeheader()
for city, total in totals.items():
    writer.writerow({"city": city, "total": total})

print(out.getvalue().strip())
city,total
Pune,4000
Mumbai,800

Putting it together: a 10-line pipeline

The same steps, as one small program built from functions. Each function does one job, which makes the program easy to read, test and change.

PythonPySpark
def read_rows(text):
    return list(csv.DictReader(io.StringIO(text)))

def clean(rows):
    good, bad = [], []
    for row in rows:
        amount = clean_amount(row["amount"])
        (bad if amount is None else good).append({**row, "amount": amount})
    return good, bad

def summarise(rows):
    result = {}
    for row in rows:
        result[row["city"]] = result.get(row["city"], 0) + row["amount"]
    return result

good, bad = clean(read_rows(raw))
print("good rows:", len(good), "| bad rows:", len(bad))
print(summarise(good))
good rows: 4 | bad rows: 1
{'Pune': 4000, 'Mumbai': 800}

You have just written a real data pipeline: read, clean, check, summarise. The tools get bigger (pandas for tables, Airflow for scheduling), but the shape stays the same.

Mistakes to avoid

  • Forgetting that CSV values are text. Convert before you calculate.
  • Letting one bad row crash the job. Use try and except, and count what you reject.
  • Writing one long script. Split it into small functions you can test.
  • Silent failures. Print or log how many rows went in, how many came out and how many were rejected.

What to learn next

  1. Tables in Python: pandas for beginners.
  2. The questions interviewers ask: Python interview questions for freshers.
  3. Practice: the free Word Frequency Counter problem uses the same dictionary-tally idea, and the full Core Python track goes much further.

Keep practising

Take what you just read into the editor.

Next in the beginner pathpandas for beginners: filter, group, merge and clean a table in PythonBrowse all 36 guides