Conversation
| from . import verification as vf | ||
| from . import visualization as plt | ||
|
|
||
| logging.getLogger(__name__).addHandler(logging.NullHandler()) |
There was a problem hiding this comment.
Maybe we can define the default handler set at INFO level to be equivalent to the print statement.
That is, no additional formatting. _logger.info(msg) equivalent to print(msg)
That will reduce the verbosity of the outputs.
We can add additional information (like time, level, etc) for the DEBUG level.
There was a problem hiding this comment.
I agree with @aperezhortal on this, we should try to mimic the current behaviour.
As a rule of thumb, we could also say that we use the INFO level for all print statements that are now unconditionally executed, while DEBUG can be used for those print statements that are currently conditional to a verbose argument or similar (e.g. the measure_time argument in the nowcast.steps() method).
There was a problem hiding this comment.
I'm changing DEBUG to INFO in the next commit, thanks for the clarifications.
aperezhortal
left a comment
There was a problem hiding this comment.
Hi @fox91, thanks for the contribution! I really like the addition of the logging module.
I made a few comments about the changes implemented.
About the logging levels, DEBUG can be used to give information about details that are of interest for diagnosing purposes. While INFO to display information about the operation of a program (only high-level things that shows that the program operates normally).
Finally, what do you think if we can start with minimal formatting (especially for INFO levels):
[LEVEL] message
or just
message
|
|
||
| logging.getLogger(__name__).addHandler(logging.NullHandler()) | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) |
There was a problem hiding this comment.
_LOGGER should be lowercase ("_logger"). Uppercase variables normally used for constants.
There was a problem hiding this comment.
I'm following pylint suggestions but I'm probably wrong.
I'm changing to lowercase with the next commit.
There was a problem hiding this comment.
Pylint expects that global variables should be uppercase. However, we try to follow a different naming convention.
There was a problem hiding this comment.
Maybe this can be another issue but: why not implement a pylintrc file in the root of the project, add to travis and enforce all code to use it?
You mention Google’s python style guide: it give you a good start point with pylintrc.
| if not rcparams.get("silent_import", False): | ||
| print("Pysteps configuration file found at: " + params_file | ||
| + "\n") | ||
| _LOGGER.debug("Pysteps configuration file found at: %s", params_file) |
There was a problem hiding this comment.
Here the logic could be:
If silent_import is True:
_logger.debug()
else:
_logger.info() # we want the behavior to be equivalent to print. This is important for runtime information.
If silent_import is True, the
| if measure_time: | ||
| computation_time = time.time() - start_time | ||
| print(f"{computation_time:.2f} seconds.") | ||
| _LOGGER.debug("%.2f seconds.", computation_time) |
There was a problem hiding this comment.
Better use INFO level here.
There was a problem hiding this comment.
Or we could remove the measure_time argument and log the computation time at DEBUG level, what do you think?
There was a problem hiding this comment.
That's a good point. But we should leave the keyword argument and add a deprecation warning to maintain backward compatibility (at least for a few releases).
There was a problem hiding this comment.
So a warnings.warn with PendingDeprecationWarning for one versione, DeprecationWarning for the next versione and total remove with the third version?
Or is best to use a DeprecationWarning for the next two version and then remove?
There was a problem hiding this comment.
Good point. According to PEP-565:
PendingDeprecationWarningis hidden by default for all code.DeprecationWarningis reported by default for code that runs directly in the__main__module (as such code is considered relatively unlikely to have a dedicated test suite), but hidden by default for code in other modules.FutureWarningis reported by default for all code. The intended audience is users of applications written in Python, rather than other Python developers
So, since we want to target the users, it seems that FutureWarning is the way to go.
| ) | ||
|
|
||
| print("Estimating nowcast parameters...", end="") | ||
| _LOGGER.debug("Estimating nowcast parameters...") |
There was a problem hiding this comment.
INFO level. This is indicating that the program is running correctly.
|
|
||
| if measure_time: | ||
| print("%.2f seconds." % (time.time() - starttime)) | ||
| _LOGGER.debug("%.2f seconds.", time.time() - starttime) |
There was a problem hiding this comment.
INFO level. This is indicating that the program is running correctly.
| @@ -8,187 +8,215 @@ | |||
|
|
|||
| """ | |||
There was a problem hiding this comment.
Maybe is a good idea to leave the examples untouched before merging the PR. In that way they show the default behavior of the library.
But this was very useful to see how the logging module worked. 👍 Perhaps, we can add a new short example showing how the logging module can be used.
There was a problem hiding this comment.
I also support the idea of a dedicated example script showing how to use the logging module.
There was a problem hiding this comment.
Using the logging module instead of print you don't see any output in the console if you don't add the proper config inside the example.
I can revert the improvements (ex: main function) but at minimum I need to add the logging.basicConfig at the top of the examples.
There was a problem hiding this comment.
We can define a default configuration in the pysteps.__init__.py that prints the INFO messages by default and add a set_loglevel function to pysteps as in matplotlib.
This is an example using matplotlib's logging implementation that logs the info messages by default. I was thinking of something along those lines.
There was a problem hiding this comment.
About that there is an open issue: matplotlib/matplotlib#13264 and a PR: matplotlib/matplotlib#13275
Personally I dislike and I'm not sure it's a good way to do the work.
There was a problem hiding this comment.
I have not found any other library that uses logging like matplotlib.
It's also true that I don't find any library that uses so many output messages like pySTEPS to be able to compare the code and evaluate how they implement the output during a normal run.
There was a problem hiding this comment.
Although it is not the same as matplotlib, TensorFlow seems to implement a default handler and an interface to control the logging level.
import logging
logger = tf.get_logger()
logger.setLevel(logging.ERROR)
| # sphinx_gallery_thumbnail_number = 5 | ||
|
|
||
|
|
||
| if __name__ == '__main__': |
There was a problem hiding this comment.
Avoid using if name == 'main' if possible. The examples should run sequentially as a script.
This will be useful in the future if we use jupyter notebooks for the examples.
|
|
||
|
|
||
| def print_ar_params(PHI): | ||
| def log_ar_params(PHI): |
There was a problem hiding this comment.
Just in case, in addition to the log_ar_params function, leave the print_ar_params for backward compatibility. We can inform to the users with a Deprecation Warning that this function will be removed in a future release.
|
|
||
|
|
||
| def print_corrcoefs(GAMMA): | ||
| def log_corrcoefs(GAMMA): |
There was a problem hiding this comment.
Just in case, in addition to the log_corrcoefs function, leave the print_corrcoefs for backward compatibility. We can inform to the users with a Deprecation Warning that this function will be removed in a future release.
| ) | ||
|
|
||
| # sphinx_gallery_thumbnail_number = 5 | ||
| logging.getLogger('matplotlib').setLevel(logging.WARNING) |
There was a problem hiding this comment.
Just out of curiosity, do you know what happens if you remove this line? Does matplotlib clutters the output with debug messages?
There was a problem hiding this comment.
In this specific example about a ten debug lines only related to internal matplotlib. Not too many but useless, so I preferred to hide them.
dnerini
left a comment
There was a problem hiding this comment.
I am also really happy about the implementation of the logging module in pysteps, thank you @fox91 for this really nice contribution!
I don't have much to add on top of what @aperezhortal already mentioned. I would say that
now we mainly need to find out the right setup that we can use for all modules.
|
Hi @fox91, do you plan to work on this PR again ? I think it would make an excellent contribution to pysteps! |
|
Hi @dnerini, |
|
Very glad to hear that you'll be able to continue on this, @fox91, thanks a lot! |

This is the PR with the
loggingmodule implemented in thepysteps.nowcastsmodule.if it seems okay I can proceed with the rest of the modules.
Fix #140 when is completed.