This script tries to parse .csv
files and returns an iterable object to fetch one row at a time to do some process. It works fine but I think it needs improvements to make it efficient.
import os
from csv import DictReader
class CSVHandler:
DELIMIT = ',' # delimiter for csv
FIELDS = set(list(['foo', 'bar'])) # fields that I want
def __init__(self, file_path: str):
self.file_path = file_path
self.file_obj = None
self.reader = DictReader([])
def read_file(self):
if self._is_file_ok:
try:
self.file_obj = open(self.file_path, newline='')
self.reader = DictReader(self.file_obj)
unmatched = self._is_fields_ok
if isinstance(unmatched, set):
print(f"Warning : field set's unmatched! {unmatched}")
except IOError:
print(f'Unable to open/read file : "{self.file_path}"')
else:
print(f'Invalid file : "{self.file_path}"')
return self
@property
def _is_file_ok(self):
if os.path.isfile(self.file_path):
if os.path.exists(self.file_path):
if self.file_path.endswith('.csv'):
return True
return False
@property
def _is_fields_ok(self):
if self.reader or not self.FIELDS:
return self.FIELDS - set(self.reader.fieldnames)
return False
def _trim_row(self, row: dict):
trimmed_row = dict.fromkeys(self.FIELDS, None)
for field in self.FIELDS:
if field in row:
trimmed_row[field] = row[field]
return trimmed_row
def __enter__(self):
return self
def __iter__(self):
return (self._trim_row(dict(row)) for row in self.reader)
def __next__(self):
return self._trim_row(dict(next(self.reader)))
def __len__(self):
return len(list(self.reader))
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file_obj is not None:
self.file_obj.close()
if __name__ == '__main__':
with CSVHandler('file_name.csv').read_file() as csv_h:
for rows in csv_h:
pass
```