If you find any mistakes here or anywhere else on my website, email website@CoryHufford.com.
September 14, 2026
Below are two Python functions for reading DSV files, useful for ephemeral data processing or visualization scripts. The second is a simplified version of the first with a few of the optional parameters missing, and it behaves as if the missing optional parameters are set to their defaults.
These functions are made for reading files that look like this:
category, count, fraction foo, 123, 0.4 bar, 456, 0.7 baz, 789, 0.0
With the optional parameters left at their defaults, this example would be parsed as the structure:
[
{"category": "foo", "count": "123", "fraction": "0.4"},
{"category": "bar", "count": "456", "fraction": "0.7"},
{"category": "baz", "count": "789", "fraction": "0.0"},
]
Parameters:
delimiterstrip_elementsFalse the first line of the above example would be parsed
as {"category": "foo", " count":
" 123",
" fraction": " 0.4"}.
skip_linescolumn_typescolumn_types = {"count": int,
"fraction": float} would produce {"category": "foo",
"count": 123, "fraction": 0.4} for the first line of the example
above.import collections.abc
import typing
def read_dsv_file_rowwise(
file_path: str,
*,
delimiter: str = ",",
strip_elements: bool = True,
skip_lines: int = 0,
column_types: collections.abc.Mapping[
str,
collections.abc.Callable[[str], typing.Any]
] = {},
) -> list[dict[str, typing.Any]]:
split_str: collections.abc.Callable[[str], list[str]] = (
(lambda s: [sub.strip() for sub in s.split(delimiter)])
if strip_elements else
(lambda s: s.split(delimiter))
)
with open(file_path, "r") as file:
for _ in range(skip_lines):
file.readline()
column_names: list[str] = split_str(file.readline().rstrip("\r\n"))
column_funcs: list[
collections.abc.Callable[[str], typing.Any] | None
] = [column_types.get(name) for name in column_names]
rows: list[dict[str, typing.Any]] = []
while line := file.readline():
if len(line := line.rstrip("\r\n")) == 0:
continue
rows.append({
name: (part if func is None else func(part))
for name, func, part
in zip(column_names, column_funcs, split_str(line))
})
return rows
import collections.abc
import typing
def read_dsv_file_rowwise(
file_path: str,
*,
delimiter: str = ",",
column_types: collections.abc.Mapping[
str,
collections.abc.Callable[[str], typing.Any]
] = {},
) -> list[dict[str, typing.Any]]:
def split_str(s: str) -> list[str]:
return [sub.strip() for sub in s.split(delimiter)]
with open(file_path, "r") as file:
column_names: list[str] = split_str(file.readline().rstrip("\r\n"))
rows: list[dict[str, typing.Any]] = []
while line := file.readline():
if len(line := line.rstrip("\r\n")) == 0:
continue
rows.append({
name: column_types.get(name, lambda x: x)(part)
for name, part in zip(column_names, split_str(line))
})
return rows