|
30 | 30 | from logging import FATAL |
31 | 31 | from logging import INFO |
32 | 32 | from logging import WARN |
| 33 | +import threading |
33 | 34 |
|
34 | 35 | import six |
35 | 36 |
|
36 | 37 | from tensorflow.python.util.all_util import remove_undocumented |
37 | 38 |
|
38 | 39 |
|
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() |
47 | 43 |
|
48 | | -# Scope the tensorflow logger to not conflict with users' loggers |
49 | | -_logger = _logging.getLogger('tensorflow') |
50 | 44 |
|
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 |
58 | 47 |
|
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() |
63 | 91 |
|
64 | 92 |
|
65 | 93 | def log(level, msg, *args, **kwargs): |
66 | | - _logger.log(level, msg, *args, **kwargs) |
| 94 | + _get_logger().log(level, msg, *args, **kwargs) |
67 | 95 |
|
68 | 96 |
|
69 | 97 | def debug(msg, *args, **kwargs): |
70 | | - _logger.debug(msg, *args, **kwargs) |
| 98 | + _get_logger().debug(msg, *args, **kwargs) |
71 | 99 |
|
72 | 100 |
|
73 | 101 | def error(msg, *args, **kwargs): |
74 | | - _logger.error(msg, *args, **kwargs) |
| 102 | + _get_logger().error(msg, *args, **kwargs) |
75 | 103 |
|
76 | 104 |
|
77 | 105 | def fatal(msg, *args, **kwargs): |
78 | | - _logger.fatal(msg, *args, **kwargs) |
| 106 | + _get_logger().fatal(msg, *args, **kwargs) |
79 | 107 |
|
80 | 108 |
|
81 | 109 | def info(msg, *args, **kwargs): |
82 | | - _logger.info(msg, *args, **kwargs) |
| 110 | + _get_logger().info(msg, *args, **kwargs) |
83 | 111 |
|
84 | 112 |
|
85 | 113 | def warn(msg, *args, **kwargs): |
86 | | - _logger.warn(msg, *args, **kwargs) |
| 114 | + _get_logger().warn(msg, *args, **kwargs) |
87 | 115 |
|
88 | 116 |
|
89 | 117 | def warning(msg, *args, **kwargs): |
90 | | - _logger.warning(msg, *args, **kwargs) |
| 118 | + _get_logger().warning(msg, *args, **kwargs) |
91 | 119 |
|
92 | 120 |
|
93 | 121 | _level_names = { |
@@ -118,7 +146,7 @@ def flush(): |
118 | 146 |
|
119 | 147 | # Code below is taken from pyglib/logging |
120 | 148 | def vlog(level, msg, *args, **kwargs): |
121 | | - _logger.log(level, msg, *args, **kwargs) |
| 149 | + _get_logger().log(level, msg, *args, **kwargs) |
122 | 150 |
|
123 | 151 |
|
124 | 152 | def _GetNextLogCountPerToken(token): |
@@ -225,12 +253,12 @@ def google2_log_prefix(level, timestamp=None, file_and_line=None): |
225 | 253 |
|
226 | 254 | def get_verbosity(): |
227 | 255 | """Return how much logging output will be produced.""" |
228 | | - return _logger.getEffectiveLevel() |
| 256 | + return _get_logger().getEffectiveLevel() |
229 | 257 |
|
230 | 258 |
|
231 | 259 | def set_verbosity(v): |
232 | 260 | """Sets the threshold for what messages will be logged.""" |
233 | | - _logger.setLevel(v) |
| 261 | + _get_logger().setLevel(v) |
234 | 262 |
|
235 | 263 |
|
236 | 264 | def _get_thread_id(): |
|
0 commit comments