Source code for rxn.utilities.csv.csv_iterator

from __future__ import annotations

import csv
from typing import Iterator, List, TextIO, Type, TypeVar

_CsvIteratorT = TypeVar("_CsvIteratorT", bound="CsvIterator")


[docs]class CsvIterator: """Class to easily iterate through CSV files while having easy access to the column names. Note: the choice to not handle the file opening/closing in this class is on purpose. This avoids issue with keeping track of which files are open and when to close them. Examples: >>> with open("some_file.csv", "rt") as f: ... csv_iterator = CsvIterator.from_stream(f) ... area_index = csv_iterator.column_index("area") ... price_index = csv_iterator.column_index("price") ... for row in csv_iterator.rows: ... price = row[price_index] ... area = row[area_index] """
[docs] def __init__(self, columns: List[str], rows: Iterator[List[str]]): self.columns = columns self.rows = rows
[docs] def column_index(self, column_name: str) -> int: """ Get the index corresponding to the given column. Args: column_name: column to look up. Raises: ValueError: if the column does not exist. Returns: the index for the given column. """ try: return self.columns.index(column_name) except ValueError: raise ValueError(f'Column "{column_name}" not found in {self.columns}.')
[docs] @classmethod def from_stream( cls: Type[_CsvIteratorT], stream: TextIO, delimiter: str = "," ) -> _CsvIteratorT: """Instantiate from a stream or file object. Args: stream: stream or file object to instantiate from. delimiter: CSV delimiter. """ reader = csv.reader(stream, delimiter=delimiter) header = next(reader) return cls(columns=header, rows=reader)
def to_stream( self, file: TextIO, delimiter: str = ",", line_terminator: str = "\n" ) -> None: writer = csv.writer(file, delimiter=delimiter, lineterminator=line_terminator) writer.writerow(self.columns) writer.writerows(self.rows)