Skip to content

Commit f701507

Browse files
taionsb2nov
authored andcommitted
Lazily configure TensorFlow logger (tensorflow#10657)
1 parent 136ba0a commit f701507

File tree

1 file changed

+59
-31
lines changed

1 file changed

+59
-31
lines changed

tensorflow/python/platform/tf_logging.py

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,64 +30,92 @@
3030
from logging import FATAL
3131
from logging import INFO
3232
from logging import WARN
33+
import threading
3334

3435
import six
3536

3637
from tensorflow.python.util.all_util import remove_undocumented
3738

3839

39-
# Determine whether we are in an interactive environment
40-
_interactive = False
41-
try:
42-
# This is only defined in interactive shells
43-
if _sys.ps1: _interactive = True
44-
except AttributeError:
45-
# Even now, we may be in an interactive shell with `python -i`.
46-
_interactive = _sys.flags.interactive
40+
# Don't use this directly. Use _get_logger() instead.
41+
_logger = None
42+
_logger_lock = threading.Lock()
4743

48-
# Scope the tensorflow logger to not conflict with users' loggers
49-
_logger = _logging.getLogger('tensorflow')
5044

51-
# If we are in an interactive environment (like jupyter), set loglevel to info
52-
# and pipe the output to stdout
53-
if _interactive:
54-
_logger.setLevel(INFO)
55-
_logging_target = _sys.stdout
56-
else:
57-
_logging_target = _sys.stderr
45+
def _get_logger():
46+
global _logger
5847

59-
# Add the output handler
60-
_handler = _logging.StreamHandler(_logging_target)
61-
_handler.setFormatter(_logging.Formatter(_logging.BASIC_FORMAT, None))
62-
_logger.addHandler(_handler)
48+
# Use double-checked locking to avoid taking lock unnecessarily.
49+
if _logger:
50+
return _logger
51+
52+
_logger_lock.acquire()
53+
54+
try:
55+
if _logger:
56+
return _logger
57+
58+
# Scope the TensorFlow logger to not conflict with users' loggers.
59+
logger = _logging.getLogger('tensorflow')
60+
61+
# Don't further configure the TensorFlow logger if the root logger is
62+
# already configured. This prevents double logging in those cases.
63+
if not _logging.getLogger().handlers:
64+
# Determine whether we are in an interactive environment
65+
_interactive = False
66+
try:
67+
# This is only defined in interactive shells.
68+
if _sys.ps1: _interactive = True
69+
except AttributeError:
70+
# Even now, we may be in an interactive shell with `python -i`.
71+
_interactive = _sys.flags.interactive
72+
73+
# If we are in an interactive environment (like Jupyter), set loglevel
74+
# to INFO and pipe the output to stdout.
75+
if _interactive:
76+
logger.setLevel(INFO)
77+
_logging_target = _sys.stdout
78+
else:
79+
_logging_target = _sys.stderr
80+
81+
# Add the output handler.
82+
_handler = _logging.StreamHandler(_logging_target)
83+
_handler.setFormatter(_logging.Formatter(_logging.BASIC_FORMAT, None))
84+
logger.addHandler(_handler)
85+
86+
_logger = logger
87+
return _logger
88+
89+
finally:
90+
_logger_lock.release()
6391

6492

6593
def log(level, msg, *args, **kwargs):
66-
_logger.log(level, msg, *args, **kwargs)
94+
_get_logger().log(level, msg, *args, **kwargs)
6795

6896

6997
def debug(msg, *args, **kwargs):
70-
_logger.debug(msg, *args, **kwargs)
98+
_get_logger().debug(msg, *args, **kwargs)
7199

72100

73101
def error(msg, *args, **kwargs):
74-
_logger.error(msg, *args, **kwargs)
102+
_get_logger().error(msg, *args, **kwargs)
75103

76104

77105
def fatal(msg, *args, **kwargs):
78-
_logger.fatal(msg, *args, **kwargs)
106+
_get_logger().fatal(msg, *args, **kwargs)
79107

80108

81109
def info(msg, *args, **kwargs):
82-
_logger.info(msg, *args, **kwargs)
110+
_get_logger().info(msg, *args, **kwargs)
83111

84112

85113
def warn(msg, *args, **kwargs):
86-
_logger.warn(msg, *args, **kwargs)
114+
_get_logger().warn(msg, *args, **kwargs)
87115

88116

89117
def warning(msg, *args, **kwargs):
90-
_logger.warning(msg, *args, **kwargs)
118+
_get_logger().warning(msg, *args, **kwargs)
91119

92120

93121
_level_names = {
@@ -118,7 +146,7 @@ def flush():
118146

119147
# Code below is taken from pyglib/logging
120148
def vlog(level, msg, *args, **kwargs):
121-
_logger.log(level, msg, *args, **kwargs)
149+
_get_logger().log(level, msg, *args, **kwargs)
122150

123151

124152
def _GetNextLogCountPerToken(token):
@@ -225,12 +253,12 @@ def google2_log_prefix(level, timestamp=None, file_and_line=None):
225253

226254
def get_verbosity():
227255
"""Return how much logging output will be produced."""
228-
return _logger.getEffectiveLevel()
256+
return _get_logger().getEffectiveLevel()
229257

230258

231259
def set_verbosity(v):
232260
"""Sets the threshold for what messages will be logged."""
233-
_logger.setLevel(v)
261+
_get_logger().setLevel(v)
234262

235263

236264
def _get_thread_id():

0 commit comments

Comments
 (0)