I'm in the middle of writing my first library module in micropython that makes use of the machine.I2C class, and as part of the bring up process for the chip, I wanted to add logging output (I2C reads/writes, etc).
For a CPython library, the logging module is included in the standard library, so you can set up debug logging within the library module like the following:
(module.py)
Code: Select all
import logging
# https://docs.python.org/3/howto/logging.html#configuring-logging-for-a-library
logging.getLogger('foo').addHandler(logging.NullHandler())
logger = logging.getLogger(__name__)
logger.debug('This is a test log message.')
(main.py)
Code: Select all
import logging
logging.basicConfig(level=logging.DEBUG)
Code: Select all
>>> import logging
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: no module named 'logging'
https://github.com/micropython/micropyt ... -274002185
The uasyncio module looks like it tries to deal with this by importing logging when DEBUG is set, but I didn't come across any other examples of how this is handled in the lib:
https://github.com/micropython/micropyt ... t__.py#L10
I'm curious if some of the more experienced folks have any best practices or standard ways of writing micropython libraries that deal with this nicely. I guess one option is to take the uasyncio approach and just document that the library requires logging.py.
Another possibility is to try to use the logging module if it exists, for example:
(module.py)
Code: Select all
try:
import logging
logger = logging.getLogger(__name__)
except ImportError:
pass
class MyDriver(object):
def _i2c_read_register(self, register, result):
...
if __debug__ and ('logging' in sys.modules) and (logger.isEnabledFor(logging.DEBUG)):
logger.debug("Read %s from register 0x%x" % (bytes(result), register))
...
def _i2c_write_register(self, register, data):
...
if __debug__ and ('logging' in sys.modules) and (logger.isEnabledFor(logging.DEBUG)):
logger.debug("Write %s to register 0x%x" % (data, register))
...