From 0c680df2f1ec8df44a1c55d45c9fb57ceb4c7a0f Mon Sep 17 00:00:00 2001 From: sjiang95 <51251025+sjiang95@users.noreply.github.com> Date: Wed, 8 May 2024 16:17:10 +0800 Subject: [PATCH] setup_logger: add optional arg `encoding` for FileHandler (#3240) * setup_logger: add optional arg encoding for FileHandler By default, the encoding is `utf-8` for compatibility with CJK characters. Signed-off-by: Shengjiang Quan * Added a test and updated docstring * open() the test log file with corresponding encoding * add Japanese and Korean test words * bypass encoding = None check on Windows * Updated tests --------- Signed-off-by: Shengjiang Quan Co-authored-by: vfdev --- ignite/utils.py | 7 ++++++- tests/ignite/test_utils.py | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ignite/utils.py b/ignite/utils.py index 078e16663f6..6e5b2176d6a 100644 --- a/ignite/utils.py +++ b/ignite/utils.py @@ -163,6 +163,7 @@ def setup_logger( filepath: Optional[str] = None, distributed_rank: Optional[int] = None, reset: bool = False, + encoding: Optional[str] = "utf-8", ) -> logging.Logger: """Setups logger: name, level, format etc. @@ -175,6 +176,7 @@ def setup_logger( distributed_rank: Optional, rank in distributed configuration to avoid logger setup for workers. If None, distributed_rank is initialized to the rank of process. reset: if True, reset an existing logger rather than keep format, handlers, and level. + encoding: open the file with the encoding. By default, 'utf-8'. Returns: logging.Logger @@ -228,6 +230,9 @@ def setup_logger( .. versionchanged:: 0.4.5 Added ``reset`` parameter. + + .. versionchanged:: 0.5.1 + Argument ``encoding`` added to correctly handle special characters in the file, default "utf-8". """ # check if the logger already exists existing = name is None or name in logging.root.manager.loggerDict @@ -265,7 +270,7 @@ def setup_logger( logger.addHandler(ch) if filepath is not None: - fh = logging.FileHandler(filepath) + fh = logging.FileHandler(filepath, encoding=encoding) fh.setLevel(level) fh.setFormatter(formatter) logger.addHandler(fh) diff --git a/tests/ignite/test_utils.py b/tests/ignite/test_utils.py index c4c65a29d69..828533ce201 100644 --- a/tests/ignite/test_utils.py +++ b/tests/ignite/test_utils.py @@ -1,4 +1,5 @@ import logging +import platform import sys from collections import namedtuple @@ -174,6 +175,29 @@ def test_override_setup_logger(capsys): logging.shutdown() +@pytest.mark.parametrize("encoding", [None, "utf-8"]) +def test_setup_logger_encoding(encoding, dirname): + fp = dirname / "log.txt" + logger = setup_logger(name="logger", filepath=fp, encoding=encoding, reset=True) + test_words = ["say hello", "say 你好", "say こんにちわ", "say 안녕하세요", "say привет"] + for w in test_words: + logger.info(w) + logging.shutdown() + + with open(fp, "r", encoding=encoding) as h: + data = h.readlines() + + if platform.system() == "Windows" and encoding is None: + flatten_data = "\n".join(data) + assert test_words[0] in flatten_data + for word in test_words[1:]: + assert word not in flatten_data + else: + assert len(data) == len(test_words) + for expected, output in zip(test_words, data): + assert expected in output + + def test_deprecated(): # Test on function without docs, @deprecated without reasons @deprecated("0.4.2", "0.6.0")