docs: def start_logging(log_fpath=None, mode='a', appname='default', log_dir=None):
      r"""
      Overwrites utool print functions to use a logger
  
      CommandLine:
          python -m utool.util_logging --test-start_logging:0
          python -m utool.util_logging --test-start_logging:1
  
      Example0:
          >>> # DISABLE_DOCTEST
          >>> import sys
          >>> sys.argv.append('--verb-logging')
          >>> import utool as ut
          >>> ut.start_logging()
          >>> ut.util_logging._utool_print()('hello world')
          >>> ut.util_logging._utool_write()('writing1')
          >>> ut.util_logging._utool_write()('writing2\n')
          >>> ut.util_logging._utool_write()('writing3')
          >>> ut.util_logging._utool_flush()()
          >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
          >>> current_log_fpath = handler.stream.name
          >>> current_log_text = ut.read_from(current_log_fpath)
          >>> print('current_log_text =\n%s' % (current_log_text,))
          >>> assert current_log_text.find('hello world') > 0, 'cant hello world'
          >>> assert current_log_text.find('writing1writing2') > 0, 'cant find writing1writing2'
          >>> assert current_log_text.find('writing3') > 0, 'cant find writing3'
  
      Example1:
          >>> # DISABLE_DOCTEST
          >>> # Ensure that progress is logged
          >>> import sys
          >>> sys.argv.append('--verb-logging')
          >>> import utool as ut
          >>> ut.start_logging()
          >>> [x for x in  ut.ProgressIter(range(0, 1000), freq=4)]
          >>> handler = ut.util_logging.__UTOOL_ROOT_LOGGER__.handlers[0]
          >>> current_log_fpath = handler.stream.name
          >>> current_log_text = ut.read_from(current_log_fpath)
          >>> assert current_log_text.find('rate') > 0, 'progress was not logged'
          >>> print(current_log_text)
      """
      global __UTOOL_ROOT_LOGGER__
      global __UTOOL_PRINT__
      global __UTOOL_WRITE__
      global __UTOOL_FLUSH__
      global __CURRENT_LOG_FPATH__
      if LOGGING_VERBOSE:
          print('[utool] start_logging()')
      # FIXME: The test for doctest may not work
  
      if __UTOOL_ROOT_LOGGER__ is None and __IN_MAIN_PROCESS__ and not __inside_doctest():
          if LOGGING_VERBOSE:
              print('[utool] start_logging()... rootcheck OK')
          #logging.config.dictConfig(LOGGING)
          if log_fpath is None:
              log_fpath = get_log_fpath(num='next', appname=appname, log_dir=log_dir)
          __CURRENT_LOG_FPATH__ = log_fpath
          # Print what is about to happen
          if VERBOSE or LOGGING_VERBOSE:
              startmsg = ('logging to log_fpath=%r' % log_fpath)
              _utool_print()(startmsg)
          # Create root logger
          __UTOOL_ROOT_LOGGER__ = logging.getLogger('root')
          __UTOOL_ROOT_LOGGER__.setLevel('DEBUG')
          # create file handler which logs even debug messages
          #fh = logging.handlers.WatchedFileHandler(log_fpath)
          logfile_handler = logging.FileHandler(log_fpath, mode=mode)
          #stdout_handler = logging.StreamHandler(__UTOOL_STDOUT__)
          stdout_handler = CustomStreamHandler(__UTOOL_STDOUT__)
          stdout_handler.terminator = ''
          # http://stackoverflow.com/questions/7168790/suppress-newline-in-python-logging-module
          #stdout_handler.terminator = ''
          add_logging_handler(logfile_handler, format_='file')
          add_logging_handler(stdout_handler, format_='stdout')
          __UTOOL_ROOT_LOGGER__.propagate = False
          __UTOOL_ROOT_LOGGER__.setLevel(logging.DEBUG)
          # Overwrite utool functions with the logging functions
  
          def utool_flush(*args):
              """ flushes whatever is in the current utool write buffer """
              # Flushes only the stdout handler
              stdout_handler.flush()
              #__UTOOL_ROOT_LOGGER__.flush()
              #global __UTOOL_WRITE_BUFFER__
              #if len(__UTOOL_WRITE_BUFFER__) > 0:
              #    msg = ''.join(__UTOOL_WRITE_BUFFER__)
              #    #sys.stdout.write('FLUSHING %r\n' % (len(__UTOOL_WRITE_BUFFER__)))
              #    __UTOOL_WRITE_BUFFER__ = []
              #    return __UTOOL_ROOT_LOGGER__.info(msg)
              #__PYTHON_FLUSH__()
  
          def utool_write(*args):
              """ writes to current utool logs and to sys.stdout.write """
              #global __UTOOL_WRITE_BUFFER__
              #sys.stdout.write('WRITEING\n')
              msg = ', '.join(map(six.text_type, args))
              #__UTOOL_WRITE_BUFFER__.append(msg)
              __UTOOL_ROOT_LOGGER__.info(msg)
              #if msg.endswith('\n'):
              #    # Flush on newline, and remove newline
              #    __UTOOL_WRITE_BUFFER__[-1] = __UTOOL_WRITE_BUFFER__[-1][:-1]
              #    utool_flush()
              #elif len(__UTOOL_WRITE_BUFFER__) > 32:
              #    # Flush if buffer is too large
              #    utool_flush()
  
          if not PRINT_ALL_CALLERS:
              def utool_print(*args):
                  """ standard utool print function """
                  #sys.stdout.write('PRINT\n')
                  endline = '\n'
                  try:
                      msg = ', '.join(map(six.text_type, args))
                      return  __UTOOL_ROOT_LOGGER__.info(msg + endline)
                  except UnicodeDecodeError:
                      new_msg = ', '.join(map(meta_util_six.ensure_unicode, args))
                      #print(new_msg)
                      return  __UTOOL_ROOT_LOGGER__.info(new_msg + endline)
          else:
              def utool_print(*args):
                  """ debugging utool print function """
                  import utool as ut
                  utool_flush()
                  endline = '\n'
                  __UTOOL_ROOT_LOGGER__.info('\n\n----------')
                  __UTOOL_ROOT_LOGGER__.info(ut.get_caller_name(range(0, 20)))
                  return  __UTOOL_ROOT_LOGGER__.info(', '.join(map(six.text_type, args)) + endline)
  
          def utool_printdbg(*args):
              """ DRPRICATE standard utool print debug function """
              return  __UTOOL_ROOT_LOGGER__.debug(', '.join(map(six.text_type, args)))
          # overwrite the utool printers
          __UTOOL_WRITE__    = utool_write
          __UTOOL_FLUSH__    = utool_flush
          __UTOOL_PRINT__    = utool_print
          # Test out our shiney new logger
          if VERBOSE or LOGGING_VERBOSE:
              __UTOOL_PRINT__('<__LOG_START__>')
              __UTOOL_PRINT__(startmsg)
      else:
          if LOGGING_VERBOSE:
              print('[utool] start_logging()... FAILED TO START')
              print('DEBUG INFO')
              print('__inside_doctest() = %r' % (__inside_doctest(),))
              print('__IN_MAIN_PROCESS__ = %r' % (__IN_MAIN_PROCESS__,))
              print('__UTOOL_ROOT_LOGGER__ = %r' % (__UTOOL_ROOT_LOGGER__,))