csv23: Python 2/3 Unicode CSV Compatibility Layer
csv23 provides the unicode-based API of the Python 3 `csv` module for Python 2 and 3. It allows code to run under both versions of Python by abstracting the bytes vs. text differences and adhering to the newer unicode-based interface. The library defaults to UTF-8 encoding and addresses several known bugs in the standard library's `csv` module. The current version is 0.3.4, and it is primarily in maintenance mode for cross-Python 2/3 compatibility features.
Common errors
-
UnicodeDecodeError: 'codec' can't decode byte ... in position ...: invalid start byte
cause The CSV file is encoded differently than the encoding specified (or defaulted to 'utf-8'). This is a common issue with CSV files from various sources.fixSpecify the correct `encoding` parameter when opening the file, e.g., `csv23.open_csv('file.csv', encoding='latin1')`. If unsure, try common encodings like 'latin1', 'cp1252', or use a library like `chardet` to detect it. You can also specify `errors='replace'` or `errors='ignore'` in the `open_csv` call to handle problematic characters. -
TypeError: DictWriter requires a 'fieldnames' parameter.
cause You are attempting to write to a CSV file using `csv23.DictWriter` (or `open_csv` with `rowtype='dict'` and `mode='w'`) without providing the `fieldnames` argument.fixProvide a list of column headers as the `fieldnames` argument when creating the `DictWriter` or calling `open_csv`. For example: `with csv23.open_csv('output.csv', 'w', rowtype='dict', fieldnames=['Header1', 'Header2']) as writer:`. -
NotImplementedError: If encoding is not 8-bit clean.
cause This error can occur in `csv23` (especially under Python 2) if an encoding that is not 8-bit clean (e.g., `utf-16`) is specified, as the library's internal optimizations for certain encodings might not support it.fixUse an 8-bit clean encoding like 'utf-8' (default) or 'latin-1' if possible. If a multi-byte encoding like 'utf-16' is truly required, you might need to handle the file opening with `io.open` or similar directly, then pass the file-like object to `csv23.reader`/`writer` (though this might bypass some `csv23` benefits).
Warnings
- breaking Version 0.3.4 is the last release to officially support Python 2. Future versions are Python 3 only.
- gotcha When using `csv23.DictWriter`, the `fieldnames` parameter is mandatory if `mode='w'` is used, similar to the standard `csv.DictWriter`.
- gotcha `csv23.NamedTupleReader` automatically uses the first row as field names. These names must be valid Python identifiers. If not, consider using `rename=True` or `rowtype='list'`.
Install
-
pip install csv23
Imports
- open_csv
import csv
from csv23 import open_csv
- reader
from csv23 import reader
- writer
from csv23 import writer
- DictReader
from csv23 import DictReader
- DictWriter
from csv23 import DictWriter
Quickstart
import csv23
import os
# Create a dummy CSV file for demonstration
file_path = 'example.csv'
data_to_write = [
['Name', 'Age', 'City'],
['Alice', '30', 'New York'],
['Bob', '24', 'London'],
['Charlie', '35', 'Paris']
]
# Writing to a CSV file
with csv23.open_csv(file_path, 'w', encoding='utf-8') as writer:
for row in data_to_write:
writer.writerow(row)
print(f"Data written to {file_path}")
# Reading from a CSV file
print("Reading data:")
with csv23.open_csv(file_path, 'r', encoding='utf-8') as reader:
for row in reader:
print(row)
# Reading as DictReader
print("\nReading data with DictReader:")
with csv23.open_csv(file_path, 'r', rowtype='dict', encoding='utf-8') as dict_reader:
for row_dict in dict_reader:
print(row_dict)
# Clean up the dummy file
os.remove(file_path)
print(f"Cleaned up {file_path}")