Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
259: The csv Module in Depth
A few years ago, I was reviewing a PR for a junior dev who was building a simple import tool for a client's product catalog. He had used line.split(',') to parse the CSV file. It worked perfectly during the first ten minutes of testing. Then, the client uploaded a real file containing a product called "Industrial Drill, Heavy Duty". Because that product name contained a comma, the split() method created an extra column, shifted all the subsequent data to the right, and crashed the database import with a type error. He spent the rest of the afternoon trying to write a complex Regular Expression to "fix" the splitting logic.
That's the exact moment I told him to stop and look at the csv module. When you're dealing with data exchange, "simple" files are rarely simple. Between quoted fields, different line endings, and varying delimiters, trying to parse CSVs manually is a recipe for a 3:00 AM debugging session.
Handling the Quoting Nightmare
The csv.reader object is your first line of defense. It doesn't just split by a character; it understands the RFC 4180 standard, which means it knows that if a comma is inside double quotes, it should be treated as part of the text, not as a column separator. I always recommend using it as an iterator to keep your memory footprint low, especially if you're dealing with massive datasets.
import csv
# Imagine 'products.csv' has a row: 101,"Industrial Drill, Heavy Duty",29.99
with open('products.csv', mode='r', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
# row is a list: ['101', 'Industrial Drill, Heavy Duty', '29.99']
print(f"Product: {row[1]} | Price: {row[2]}")
Notice the newline='' argument in open(). Don't skip this. The csv module handles its own newline translation; if you let Python's open() do it too, you'll often end up with mysterious blank lines between your data rows on Windows machines.
Mapping Data with DictReader and DictWriter
While index-based access (like row[1]) is fast, it's fragile. If the client adds a "Category" column to the middle of the CSV, your entire script breaks. This is where DictReader becomes a lifesaver. It uses the first row of the file as keys, turning every subsequent row into a dictionary.
import csv
with open('products.csv', mode='r', newline='', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
# Now we use the column name, which is much more readable
print(f"Item: {row['ProductName']} - SKU: {row['SKU']}")
Writing data is just as streamlined. If you use DictWriter, you define the fieldnames upfront. I personally prefer this over the standard csv.writer because it forces you to be explicit about which columns you are actually exporting, preventing those dreaded "shifted column" errors in the output file.
Taming Non-Standard Delimiters and Dialects
In the real world, you'll encounter "CSVs" that aren't actually comma-separated. You'll find TSVs (tab-separated) or files from European legacy systems that use semicolons because commas are used as decimal points. You don't need a different library for this; you just need to define the delimiter.
If you find yourself repeatedly configuring the same set of parameters (delimiter, quoting style, line terminator), you can create a csv.Dialect. It's essentially a named configuration profile that you can pass into your reader or writer. It keeps your code clean and ensures consistency across different modules of your application.
import csv
# Handling a semicolon-separated file from a legacy system
with open('legacy_data.csv', mode='r', newline='') as f:
reader = csv.reader(f, delimiter=';', quotechar='"')
for row in reader:
print(row)
📋 Practical Task
Exercise: The Messy Logistics Log Cleaner
You've been handed a logistics log file called shipments.log. The file is "CSV-like," but it uses a pipe (|) as a delimiter and occasionally wraps fields in single quotes (') instead of double quotes.
Your Task: Write a Python script that does the following:
- Reads the
shipments.logfile using thecsvmodule. - Handles the pipe delimiter and the single-quote character.
- Filters out any rows where the "Status" column is marked as
'Cancelled'. - Writes the remaining "Active" or "Shipped" rows into a new file called
cleaned_shipments.csvusing standard comma delimiters and double-quote formatting.
Sample input data for shipments.log:
ID|Customer|Status|Weight
101|'Acme Corp'|'Shipped'|15.5
102|'Globex'|'Cancelled'|2.0
103|'Soylent Co'|'Active'|45.2
There are no comments for now.