File size: 2,076 Bytes
ccba775
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""

Simple logging utilities for experiments.



Provides a minimal CSVLogger that creates the output directory if needed,

writes a header once, and appends rows as dictionaries.

"""

from __future__ import annotations

import csv
import os
from typing import Mapping, Sequence


class CSVLogger:
    """

    Minimal CSV logger for experiment metrics.



    Parameters

    ----------

    filepath : str

        Path to the CSV file to create/append.

    fieldnames : Sequence[str]

        Ordered list of column names to use as the CSV header.



    Notes

    -----

    - The directory containing `filepath` is created if it does not exist.

    - The file is overwritten when the logger is constructed.

    - Each call to `log` appends a single row.

    """

    def __init__(self, filepath: str, fieldnames: Sequence[str]) -> None:
        self.filepath = filepath
        # Handle the case where filepath is in the current directory.
        directory = os.path.dirname(filepath)
        if directory:
            os.makedirs(directory, exist_ok=True)

        self.fieldnames = list(fieldnames)
        self._init_file()

    def _init_file(self) -> None:
        """Create or overwrite the CSV file and write the header row."""
        with open(self.filepath, mode="w", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=self.fieldnames)
            writer.writeheader()

    def log(self, row_dict: Mapping[str, object]) -> None:
        """

        Append a single row to the CSV file.



        Parameters

        ----------

        row_dict : Mapping[str, object]

            Dictionary mapping field name to value. Missing keys will be

            written as empty cells; extra keys are ignored.

        """
        # Project to known fieldnames to avoid surprises.
        row = {k: row_dict.get(k, "") for k in self.fieldnames}
        with open(self.filepath, mode="a", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=self.fieldnames)
            writer.writerow(row)