From c115aa367f56a24be826afd7d89ab299d3d0b91a Mon Sep 17 00:00:00 2001 From: Juho Inkinen Date: Tue, 25 Apr 2023 14:40:59 +0300 Subject: [PATCH 1/8] Suppress TF info messages during import --- annif/backend/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/annif/backend/__init__.py b/annif/backend/__init__.py index cbeeb648e..ccc9fad74 100644 --- a/annif/backend/__init__.py +++ b/annif/backend/__init__.py @@ -1,6 +1,7 @@ """Registry of backend types for Annif""" from __future__ import annotations +import os from typing import TYPE_CHECKING, Type if TYPE_CHECKING: @@ -43,8 +44,12 @@ def _mllm() -> Type[AnnifBackend]: def _nn_ensemble() -> Type[AnnifBackend]: try: + os.environ["TF_CPP_MIN_LOG_LEVEL"] = "1" + from . import nn_ensemble + os.environ["TF_CPP_MIN_LOG_LEVEL"] = "0" + return nn_ensemble.NNEnsembleBackend except ImportError: raise ValueError( From 1b56185430c24fdf7fabcfbdda828d8bb5edb3b4 Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:05:56 +0300 Subject: [PATCH 2/8] Suppress all TF info messages by default --- annif/backend/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/annif/backend/__init__.py b/annif/backend/__init__.py index ccc9fad74..dba5aecf7 100644 --- a/annif/backend/__init__.py +++ b/annif/backend/__init__.py @@ -44,12 +44,11 @@ def _mllm() -> Type[AnnifBackend]: def _nn_ensemble() -> Type[AnnifBackend]: try: - os.environ["TF_CPP_MIN_LOG_LEVEL"] = "1" + # Hide TF info messages by default + os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "1") from . import nn_ensemble - os.environ["TF_CPP_MIN_LOG_LEVEL"] = "0" - return nn_ensemble.NNEnsembleBackend except ImportError: raise ValueError( From 31af009d852897e4487eab995b95e1e47e798b5f Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:50:03 +0300 Subject: [PATCH 3/8] Suppress all TF info messages by default, really --- annif/__init__.py | 1 + annif/backend/__init__.py | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/annif/__init__.py b/annif/__init__.py index bb196b4ee..872af8d3f 100644 --- a/annif/__init__.py +++ b/annif/__init__.py @@ -10,6 +10,7 @@ logging.basicConfig() logger = logging.getLogger("annif") logger.setLevel(level=logging.INFO) +os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "1") # Hide TF info messages by default import annif.backend # noqa diff --git a/annif/backend/__init__.py b/annif/backend/__init__.py index dba5aecf7..cbeeb648e 100644 --- a/annif/backend/__init__.py +++ b/annif/backend/__init__.py @@ -1,7 +1,6 @@ """Registry of backend types for Annif""" from __future__ import annotations -import os from typing import TYPE_CHECKING, Type if TYPE_CHECKING: @@ -44,9 +43,6 @@ def _mllm() -> Type[AnnifBackend]: def _nn_ensemble() -> Type[AnnifBackend]: try: - # Hide TF info messages by default - os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "1") - from . import nn_ensemble return nn_ensemble.NNEnsembleBackend From 642498bf49970336401b91a8503aee321eb5a71e Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Wed, 2 Aug 2023 10:50:31 +0300 Subject: [PATCH 4/8] Set TF log level by mapping Annif log level --- annif/__init__.py | 17 ++++++++++++++++- tests/test_cli.py | 21 +++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/annif/__init__.py b/annif/__init__.py index 872af8d3f..72ff493c9 100644 --- a/annif/__init__.py +++ b/annif/__init__.py @@ -10,7 +10,6 @@ logging.basicConfig() logger = logging.getLogger("annif") logger.setLevel(level=logging.INFO) -os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", "1") # Hide TF info messages by default import annif.backend # noqa @@ -22,6 +21,8 @@ def create_flask_app(config_name: str | None = None) -> Flask: """Create a Flask app to be used by the CLI.""" from flask import Flask + _set_tensorflow_loglevel() + app = Flask(__name__) config_name = _get_config_name(config_name) logger.debug(f"creating flask app with configuration {config_name}") @@ -76,3 +77,17 @@ def _get_config_name(config_name: str | None) -> str: else: config_name = "annif.default_config.ProductionConfig" # pragma: no cover return config_name + + +def _set_tensorflow_loglevel(): + annif_loglevel = logger.getEffectiveLevel() + tf_loglevel_mapping = { + 0: "0", # NOTSET + 10: "0", # DEBUG + 20: "1", # INFO + 30: "2", # WARNING + 40: "3", # ERROR + 50: "3", # CRITICAL + } + tf_loglevel = tf_loglevel_mapping[annif_loglevel] + os.environ.setdefault("TF_CPP_MIN_LOG_LEVEL", tf_loglevel) diff --git a/tests/test_cli.py b/tests/test_cli.py index ef44df8a3..30bdc64ea 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1122,3 +1122,24 @@ def test_completion_show_project_project_ids_dummy(): def test_completion_load_vocab_vocab_ids_all(): completions = get_completions(annif.cli.cli, ["load-vocab"], "") assert completions == ["dummy", "dummy-noname", "yso"] + + +def test_tensorflow_loglevel(): + tf_env = "TF_CPP_MIN_LOG_LEVEL" + assert tf_env not in os.environ.keys() + + runner.invoke(annif.cli.cli, ["list-projects", "-v", "DEBUG"]) + assert os.environ[tf_env] == "0" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects"]) # INFO level by default + assert os.environ[tf_env] == "1" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "WARN"]) + assert os.environ[tf_env] == "2" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "ERROR"]) + assert os.environ[tf_env] == "3" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "CRITICAL"]) + assert os.environ[tf_env] == "3" + os.environ.pop(tf_env) From a59c52ee021d647e7309e779c58c9eead8fd3397 Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Wed, 2 Aug 2023 19:01:09 +0300 Subject: [PATCH 5/8] Make tests pass If this test is run after other tests with @mock.patch.dict(os.environ,...), the tests with caplog fixture in test_config.py fail --- tests/test_cli.py | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 30bdc64ea..14ca9e830 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -23,6 +23,27 @@ PROJECTS_CONFIG_PATH = "tests/projects_for_config_path_option.cfg" +@mock.patch.dict(os.environ, clear=True) +def test_tensorflow_loglevel(): + tf_env = "TF_CPP_MIN_LOG_LEVEL" + + runner.invoke(annif.cli.cli, ["list-projects", "-v", "DEBUG"]) + assert os.environ[tf_env] == "0" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects"]) # INFO level by default + assert os.environ[tf_env] == "1" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "WARN"]) + assert os.environ[tf_env] == "2" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "ERROR"]) + assert os.environ[tf_env] == "3" + os.environ.pop(tf_env) + runner.invoke(annif.cli.cli, ["list-projects", "-v", "CRITICAL"]) + assert os.environ[tf_env] == "3" + os.environ.pop(tf_env) + + def test_list_projects(): result = runner.invoke(annif.cli.cli, ["list-projects"]) assert not result.exception @@ -1122,24 +1143,3 @@ def test_completion_show_project_project_ids_dummy(): def test_completion_load_vocab_vocab_ids_all(): completions = get_completions(annif.cli.cli, ["load-vocab"], "") assert completions == ["dummy", "dummy-noname", "yso"] - - -def test_tensorflow_loglevel(): - tf_env = "TF_CPP_MIN_LOG_LEVEL" - assert tf_env not in os.environ.keys() - - runner.invoke(annif.cli.cli, ["list-projects", "-v", "DEBUG"]) - assert os.environ[tf_env] == "0" - os.environ.pop(tf_env) - runner.invoke(annif.cli.cli, ["list-projects"]) # INFO level by default - assert os.environ[tf_env] == "1" - os.environ.pop(tf_env) - runner.invoke(annif.cli.cli, ["list-projects", "-v", "WARN"]) - assert os.environ[tf_env] == "2" - os.environ.pop(tf_env) - runner.invoke(annif.cli.cli, ["list-projects", "-v", "ERROR"]) - assert os.environ[tf_env] == "3" - os.environ.pop(tf_env) - runner.invoke(annif.cli.cli, ["list-projects", "-v", "CRITICAL"]) - assert os.environ[tf_env] == "3" - os.environ.pop(tf_env) From a2971eb2ae419804ba4b30b100f8af17bf338513 Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Wed, 2 Aug 2023 19:22:55 +0300 Subject: [PATCH 6/8] Alter level mapping Tone down only TensorFlow INFO level: INFO messages by TFare shown only when running Annif at DEBUG level --- annif/__init__.py | 4 ++-- tests/test_cli.py | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/annif/__init__.py b/annif/__init__.py index 72ff493c9..f69b99685 100644 --- a/annif/__init__.py +++ b/annif/__init__.py @@ -85,8 +85,8 @@ def _set_tensorflow_loglevel(): 0: "0", # NOTSET 10: "0", # DEBUG 20: "1", # INFO - 30: "2", # WARNING - 40: "3", # ERROR + 30: "1", # WARNING + 40: "2", # ERROR 50: "3", # CRITICAL } tf_loglevel = tf_loglevel_mapping[annif_loglevel] diff --git a/tests/test_cli.py b/tests/test_cli.py index 14ca9e830..55b5dfd07 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -28,19 +28,19 @@ def test_tensorflow_loglevel(): tf_env = "TF_CPP_MIN_LOG_LEVEL" runner.invoke(annif.cli.cli, ["list-projects", "-v", "DEBUG"]) - assert os.environ[tf_env] == "0" + assert os.environ[tf_env] == "0" # Show INFO, WARNING and ERROR messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects"]) # INFO level by default - assert os.environ[tf_env] == "1" + assert os.environ[tf_env] == "1" # Show WARNING and ERROR messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects", "-v", "WARN"]) - assert os.environ[tf_env] == "2" + assert os.environ[tf_env] == "1" # Show WARNING and ERROR messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects", "-v", "ERROR"]) - assert os.environ[tf_env] == "3" + assert os.environ[tf_env] == "2" # Show no messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects", "-v", "CRITICAL"]) - assert os.environ[tf_env] == "3" + assert os.environ[tf_env] == "3" # Show no messages by TF os.environ.pop(tf_env) From c016754acf330610a5454de469a9c424a2e04609 Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Thu, 3 Aug 2023 11:20:19 +0300 Subject: [PATCH 7/8] Fix comment on TF level --- tests/test_cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 55b5dfd07..77adeab0f 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -37,7 +37,7 @@ def test_tensorflow_loglevel(): assert os.environ[tf_env] == "1" # Show WARNING and ERROR messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects", "-v", "ERROR"]) - assert os.environ[tf_env] == "2" # Show no messages by TF + assert os.environ[tf_env] == "2" # Show ERROR messages by TF os.environ.pop(tf_env) runner.invoke(annif.cli.cli, ["list-projects", "-v", "CRITICAL"]) assert os.environ[tf_env] == "3" # Show no messages by TF From 80c0fe26a81358e7d9f695d5a17de54805a68fc8 Mon Sep 17 00:00:00 2001 From: Juho Inkinen <34240031+juhoinkinen@users.noreply.github.com> Date: Thu, 3 Aug 2023 11:42:32 +0300 Subject: [PATCH 8/8] Add docstring --- annif/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/annif/__init__.py b/annif/__init__.py index f69b99685..a71b9f379 100644 --- a/annif/__init__.py +++ b/annif/__init__.py @@ -80,6 +80,9 @@ def _get_config_name(config_name: str | None) -> str: def _set_tensorflow_loglevel(): + """Set TensorFlow log level based on Annif log level (--verbosity/-v + option) using an environment variable. INFO messages by TF are shown only on + DEBUG (or NOTSET) level of Annif.""" annif_loglevel = logger.getEffectiveLevel() tf_loglevel_mapping = { 0: "0", # NOTSET