class_docstr: Standard CSV logger.
  
  The fields are inferred from the first call to write() and any additional
  fields afterwards are ignored.
  
  TODO(jaslanides): Consider making this stateless/robust to preemption.
class_docstr_tok: ["Standard","CSV","logger",".","The","fields","are","inferred","from","the","first","call","to","write","(",")","and","any","additional","fields","afterwards","are","ignored",".","TODO","(","jaslanides",")",":","Consider","making","this","stateless\/robust","to","preemption","."]
docstr: Writes a `data` into a row of comma-separated values.
docstr_tok: ["Writes","a","`","data","`","into","a","row","of","comma-separated","values","."]
code: def write(self, data: base.LoggingData):
      """Writes a `data` into a row of comma-separated values."""
      # Only log if `time_delta` seconds have passed since last logging event.
      now = time.time()
  
      # TODO(b/192227744): Remove this in favour of filters.TimeFilter.
      elapsed = now - self._last_log_time
      if elapsed < self._time_delta:
          logging.debug(
              "Not due to log for another %.2f seconds, dropping data.",
              self._time_delta - elapsed,
          )
          return
      self._last_log_time = now
  
      # Append row to CSV.
      data = base.to_numpy(data)
      # Use fields from initial `data` to create the header. If extra fields are
      # present in subsequent `data`, we ignore them.
      if not self._writer:
          fields = sorted(data.keys())
          self._writer = csv.DictWriter(
              self._file, fieldnames=fields, extrasaction="ignore"
          )
          # Write header only if the file is empty.
          if not self._file.tell():
              self._writer.writeheader()
      self._writer.writerow(data)
  
      # Flush every `flush_every` writes.
      if self._writes % self._flush_every == 0:
          self.flush()
      self._writes += 1
  
file_path: acme/acme/utils/loggers/csv.py
imports: import csv
  import os
  import time
  from typing import TextIO, Union
  from absl import logging
  from acme.utils import paths
  from acme.utils.loggers import base
label_desc: Use image node_id 3 for calling the CSVLogger obj's underlying member method code with example usage: obj.write(data) without return types