Logging, Warnings, and Exceptions#

Overview#

sunpy makes use of a logging system to deal with messages (see Logger Objects). This provides the users and developers the ability to decide which messages to show, to capture them, and to optionally also send them to a file. The logger will log all messages issued directly to it but also warnings issued through warnings.warn as well as exceptions.

The logger is configured as soon as sunpy is imported. You can access it by importing it explicitly:

from sunpy import log

Messages can be issued directly to it with the following levels and in the following way:

log.debug("Detailed information, typically of interest only when diagnosing problems.")

log.info("A message conveying information about the current task, and confirming that
          things are working as expected.")

log.warning("An indication that something unexpected happened, or indicative of
             some problem in the near future (e.g. disk space low).

             The software is still working as expected.")
log.error("Due to a more serious problem, the software has not been able to
           perform some function but the task is still continuing.")

log.critical("A serious error, indicating that the program itself may be unable to
              continue running. A real error may soon by issued and the task will fail.")

The difference between logging a warning/error/critical compared to issuing a Python warning or raising an exception are subtle but important.

Use Python warnings.warn in library code if the issue is avoidable and the user code should be modified to eliminate the warning.

Use log.warning() if there is likely nothing the user can do about the situation, but the event should still be noted. An example of this might be if the input data are all zeros. This may be unavoidable or even by design but you may want to let the user know.

True exceptions (not log.error()) should be raised only when there is no way for the function to proceed.

Regardless of the type (log message or warning or exception) messages should be one or two complete sentences that fully describe the issue and end with a period.

Issuing Warnings#

sunpy warnings are provided by the sunpy.util module. The primary warning which should be used is sunpy.util.exceptions.SunpyUserWarning. For deprecation use sunpy.util.exceptions.SunpyDeprecationWarning or sunpy.util.exceptions.SunpyPendingDeprecationWarning.

These three warning types have corresponding functions to raise them:

>>> from sunpy.util.exceptions import warn_user
>>> from sunpy.util.exceptions import warn_deprecated
>>> from sunpy.util.exceptions import warn_metadata

These warning functions must be used to interact correctly with the logging system. A warning can be issued in the following way:

>>> from sunpy.util.exceptions import warn_user
>>> warn_user("You have been warned about something you did not do correctly.")  

See the section above for a discussion about the distinction between log.warn() and raising a warning.

Raising Exceptions#

Raising errors causes the program to halt. Likely the primary error that a sunpy developer will want to use is

  • ValueError: should be raised if the input is not what was expected and could not be used. Functions should not return anything (like None) in that case or issue a warning.

Exceptions are raised simply with:

>>> raise ValueError("The following error occurred.")  

For more information on exceptions see the Built-in Exceptions documentation.