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: Opens a file if input is a directory or use existing file.
docstr_tok: ["Opens","a","file","if","input","is","a","directory","or","use","existing","file","."]
code: def _create_file(
      self,
      directory_or_file: Union[str, TextIO],
      label: str,
  ) -> TextIO:
      """Opens a file if input is a directory or use existing file."""
      if isinstance(directory_or_file, str):
          directory = paths.process_path(
              directory_or_file, "logs", label, add_uid=self._add_uid
          )
          file_path = os.path.join(directory, "logs.csv")
          self._file_owner = True
          return self._open(file_path, mode="a")
  
      # TextIO instance.
      file = directory_or_file
      if label:
          logging.info(
              "File, not directory, passed to CSVLogger; label not used."
          )
      if not file.mode.startswith("a"):
          raise ValueError(
              "File must be open in append mode; instead got "
              f'mode="{file.mode}".'
          )
      return file
  
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 2 for calling the CSVLogger obj's underlying member method code with example usage: obj._create_file(directory_or_file, label) and returns: file, self