A CSV file can open successfully and still contain unusable data. A blank customer name, a negative quantity or a text value in a numeric column can silently distort a report. The first goal of a validator is to explain which row failed and why, while preserving the original file for investigation.
For this exercise, each row needs a name and an integer quantity of zero or more. Zero is valid; an empty value is not. These are business rules, not properties that the CSV format enforces. Write the rules down before deciding whether to reject, repair or quarantine bad rows.
import csv
from io import StringIO
sample = StringIO("name,quantity\nAsha,3\n,2\nRavi,abc\nMina,-1\n")
errors = []
valid = []
for row_number, row in enumerate(csv.DictReader(sample), start=2):
reasons = []
if not (row.get("name") or "").strip():
reasons.append("name is missing")
try:
quantity = int(row.get("quantity") or "")
if quantity < 0:
reasons.append("quantity is negative")
except ValueError:
reasons.append("quantity is not an integer")
if reasons:
errors.append({"row": row_number, "errors": reasons})
else:
valid.append(row)
print(len(valid), len(errors)) # 1 3The example labels the header as line 1 and begins data rows at 2. It catches conversion errors for individual rows rather than stopping the whole import. It deliberately does not turn invalid quantities into zero: that would make missing data indistinguishable from an actual zero quantity. With quoted multiline fields, a CSV record number is not necessarily the physical line number.
For an actual file, open it with an explicit encoding and newline="" as recommended by the csv documentation. Confirm the header names before processing rows, then decide whether any error should block the entire import. Keep a separate report containing a record identifier and validation messages; avoid copying unnecessary personal information into logs.
A validator that accepts one clean file has not demonstrated its rejection behavior. Test whitespace-only names, missing columns, an empty file and quantities such as 3.5. Decide whether surrounding whitespace, leading zeros and plus signs are permitted. Document those choices so a later change does not quietly alter the contract.
Add a required item_code column and reject duplicate codes within the input. Produce separate counts for accepted rows, invalid rows and duplicates. Test quantity 0 and confirm it remains valid.
Explore the related Code Hacker course syllabus for structured learning. Then read Python Exception Handling for a Reliable Import Pipeline to connect this exercise to the next skill.
Python csv module provides the underlying API or technical guidance. Check the documentation for the version you use; examples here are small learning exercises rather than complete production implementations.
Found an issue with this guide? Send a correction with the article URL and your example. About our learning material.
Subscribe to Code Hacker and get hands-on access to 40+ premium courses — Ethical Hacking, Kali Linux, Metasploit, Network Hacking, Bug Bounty & more!