You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2022/05/24 16:38:56 UTC
[GitHub] [tvm] guberti commented on issue #11117: [CI Problem] CI has logging errors even when successful
guberti commented on issue #11117:
URL: https://github.com/apache/tvm/issues/11117#issuecomment-1136152256
This issue is causing me quite a headache, as it is blocking me from merging #10921. I think I've figured it out though - it's caused by an interaction between `sphinx-gallery` and `absl` (imported by `tensorflow`). Here's what happens:
1. `sphinx-gallery` wants to capture the output of code blocks as it runs them (this is one of its main features). To do this, [it uses a custom `LoggingTee` object](https://github.com/sphinx-gallery/sphinx-gallery/blob/master/sphinx_gallery/gen_rst.py#L60-L72) to replace `sys.stdout` and `sys.stderr`:
```python
class _LoggingTee(object):
"""A tee object to redirect streams to the logger."""
...
def set_std_and_reset_position(self):
if not isinstance(sys.stdout, _LoggingTee):
self.origs = (sys.stdout, sys.stderr)
sys.stdout = sys.stderr = self
```
2. `tensorflow` wants to have nice logging features, so it imports `logging` from [`absl`](https://abseil.io/). Hence, an `absl` `PythonHandler`, which is a subclass of Python's `StreamHandler`, is created.
3. When a `StreamHandler` is created, it creates a pointer to `sys.stderr`. However, since `sphinx-gallery` replaced `sys.stderr` with `LoggingTee` earlier, a `LoggingTee` is instead inserted here:
```python
class StreamHandler(Handler):
def __init__(self, stream=None):
"""
Initialize the handler.
If stream is not specified, sys.stderr is used.
"""
Handler.__init__(self)
if stream is None:
stream = sys.stderr
self.stream = stream
```
4. The error does not happen until `sphinx-gallery` finishes executing the code block. When this occurs, `sphinx-gallery` attempts to switch `stderr` and `stdout` back to their original values. However, it does not know that `StreamHandler` has a pointer to the `LoggingTee` object, and is unable to fix it. Hence, `stdout` and `stderr` go back to their original values, but `self.stream` in `StreamHandler` has the `LoggingTee`.
```python
def restore_std(self):
sys.stdout.flush()
sys.stderr.flush()
sys.stdout, sys.stderr = self.origs
```
5. When it is time to close the log with `absl`, the `close` function is called:
```python
def close(self):
"""Closes the stream to which we are writing."""
self.acquire()
try:
self.flush()
try:
# Do not close the stream if it's sys.stderr|stdout. They may be
# redirected or overridden to files, which should be managed by users
# explicitly.
user_managed = sys.stderr, sys.stdout, sys.__stderr__, sys.__stdout__
if self.stream not in user_managed and (
not hasattr(self.stream, 'isatty') or not self.stream.isatty()):
self.stream.close()
except ValueError:
# A ValueError is thrown if we try to run isatty() on a closed file.
pass
super(PythonHandler, self).close()
finally:
self.release()
```
We **should not call `close`** if we are writing to `stderr` or `stdout`, and `absl` knows this. Hence it checks whether `self.stream` is equal to either `sys.stderr` or `sys.stdout`. However, since `self.stream` is the `LoggingTee` object, it sees that it is not equal, and assumes the stream is a file that needs closing.
6. `close()` is then called on `LoggingTee`, which does not have a `close()` method. This yields the `AttributeError` found above.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org