{"id":7118,"library":"csv23","title":"csv23: Python 2/3 Unicode CSV Compatibility Layer","description":"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.","status":"maintenance","version":"0.3.4","language":"en","source_language":"en","source_url":"https://github.com/xflr6/csv23","tags":["csv","unicode","python2","python3","compatibility","data-processing","file-io"],"install":[{"cmd":"pip install csv23","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Explicitly designed for Python 2.7+ and 3.x (excluding 3.0-3.6 for direct support in v0.3.4, though it provides Python 3 CSV API). Future versions beyond 0.3.4 are Python 3 only.","package":"python","optional":false}],"imports":[{"note":"While `csv23` mimics the standard `csv` module, direct import of `csv` won't provide the compatibility layer. Use `csv23.open_csv` for the primary context manager.","wrong":"import csv","symbol":"open_csv","correct":"from csv23 import open_csv"},{"note":"For direct access to the `reader` class.","symbol":"reader","correct":"from csv23 import reader"},{"note":"For direct access to the `writer` class.","symbol":"writer","correct":"from csv23 import writer"},{"note":"For reading CSV data into dictionaries.","symbol":"DictReader","correct":"from csv23 import DictReader"},{"note":"For writing dictionaries to CSV.","symbol":"DictWriter","correct":"from csv23 import DictWriter"}],"quickstart":{"code":"import csv23\nimport os\n\n# Create a dummy CSV file for demonstration\nfile_path = 'example.csv'\ndata_to_write = [\n    ['Name', 'Age', 'City'],\n    ['Alice', '30', 'New York'],\n    ['Bob', '24', 'London'],\n    ['Charlie', '35', 'Paris']\n]\n\n# Writing to a CSV file\nwith csv23.open_csv(file_path, 'w', encoding='utf-8') as writer:\n    for row in data_to_write:\n        writer.writerow(row)\nprint(f\"Data written to {file_path}\")\n\n# Reading from a CSV file\nprint(\"Reading data:\")\nwith csv23.open_csv(file_path, 'r', encoding='utf-8') as reader:\n    for row in reader:\n        print(row)\n\n# Reading as DictReader\nprint(\"\\nReading data with DictReader:\")\nwith csv23.open_csv(file_path, 'r', rowtype='dict', encoding='utf-8') as dict_reader:\n    for row_dict in dict_reader:\n        print(row_dict)\n\n# Clean up the dummy file\nos.remove(file_path)\nprint(f\"Cleaned up {file_path}\")","lang":"python","description":"This quickstart demonstrates how to use `csv23.open_csv` as a context manager for both writing and reading CSV files, ensuring proper encoding handling. It also shows how to use `DictReader` to parse rows as dictionaries."},"warnings":[{"fix":"For Python 2 compatibility, pin to `csv23==0.3.4`. For new projects targeting only Python 3, `csv23` still offers useful wrappers but direct `csv` module use might suffice.","message":"Version 0.3.4 is the last release to officially support Python 2. Future versions are Python 3 only.","severity":"breaking","affected_versions":">=0.3.5"},{"fix":"Always provide the `fieldnames` keyword argument when initializing `DictWriter` or `open_csv(..., rowtype='dict', mode='w', fieldnames=...)`.","message":"When using `csv23.DictWriter`, the `fieldnames` parameter is mandatory if `mode='w'` is used, similar to the standard `csv.DictWriter`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If header names contain special characters (e.g., spaces, hyphens) which are invalid Python identifiers, pass `rename=True` to `open_csv` when `rowtype='namedtuple'` to automatically convert them to valid names (e.g., `_0`, `_1`).","message":"`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'`.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Specify 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.","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.","error":"UnicodeDecodeError: 'codec' can't decode byte ... in position ...: invalid start byte"},{"fix":"Provide 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:`.","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.","error":"TypeError: DictWriter requires a 'fieldnames' parameter."},{"fix":"Use 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).","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.","error":"NotImplementedError: If encoding is not 8-bit clean."}]}