Source code for dowel.csv_output

"""A `dowel.logger.LogOutput` for CSV files."""
import csv
import os

from dowel import TabularInput
from dowel.simple_outputs import FileOutput


[docs]class CsvOutput(FileOutput): """CSV file output for logger. :param file_name: The file this output should log to. """ def __init__(self, file_name): super().__init__(file_name) self._writer = None self._fieldnames = None self._filename = file_name @property def types_accepted(self): """Accept TabularInput objects only.""" return (TabularInput, )
[docs] def record(self, data, prefix=''): """Log tabular data to CSV.""" if isinstance(data, TabularInput): to_csv = data.as_primitive_dict if not self._writer: self._fieldnames = set(to_csv.keys()) self._writer = csv.DictWriter(self._log_file, fieldnames=self._fieldnames, restval='', extrasaction='raise') self._writer.writeheader() if to_csv.keys() != self._fieldnames: # Close existing log file super().close() # Move log file to temp file temp_file_name = '{}.tmp'.format(self._filename) os.replace(self._filename, temp_file_name) # Add new keys to fieldnames self._fieldnames = (set(self._fieldnames) | set(to_csv.keys())) # Open a new copy of the log file self._log_file = open(self._filename, 'w') self._writer = csv.DictWriter(self._log_file, fieldnames=self._fieldnames, restval='', extrasaction='raise') # Transfer data from temp file with open(temp_file_name, 'r') as temp_file: self._writer.writeheader() for row in csv.DictReader(temp_file): self._writer.writerow(row) self._writer.writerow(to_csv) for k in to_csv.keys(): data.mark(k) else: raise ValueError('Unacceptable type.')