Last active
July 18, 2021 09:59
-
-
Save decatur/a90146b1aaddd679b89a3291adf86b46 to your computer and use it in GitHub Desktop.
So you want your stdout, stderr and logs in a file, but you only know the final log file name somewhere down the road?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
So you want your stdout, stderr and logs in a file, but you only know the final log file name somewhere down the road? | |
""" | |
import io | |
import sys | |
import threading | |
from pathlib import Path | |
from typing import IO, cast | |
class NameChangingStream(io.TextIOBase): | |
def __init__(self, initial_path: Path): | |
self.buffer = initial_path.open('w') | |
self.lock = threading.RLock() | |
def change_name(self, final_path: Path): | |
assert self.lock, 'change_name() called twice' | |
self.lock.acquire() | |
self.buffer.flush() | |
self.buffer.close() | |
final_path = Path(self.buffer.buffer.raw.name).replace(final_path) | |
self.buffer = final_path.open('a') | |
self.lock.release() | |
self.lock = None | |
def write(self, s): | |
if self.lock: | |
self.lock.acquire() | |
self.buffer.write(s) | |
self.lock.release() | |
else: | |
self.buffer.write(s) | |
def test_usage(): | |
stream = cast(IO, NameChangingStream(Path('initial.log'))) # https://youtrack.jetbrains.com/issue/PY-23288 | |
sys.stdout = sys.stderr = stream | |
import logging | |
logger = logging.getLogger() | |
logger.setLevel(logging.DEBUG) | |
assert not logger.handlers | |
handler = logging.StreamHandler(stream) | |
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') | |
handler.setFormatter(formatter) | |
logger.addHandler(handler) | |
logger.info('Hello') | |
logger.info('World') | |
if isinstance(stream, NameChangingStream): | |
stream.change_name(Path('final.log')) | |
logger.debug('Hello') | |
logger.debug('World') | |
print('FooBar') | |
assert False, 'Goes to Log!' | |
test_usage() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment