I've got a logging handler setup that prints to stream and file. I'm working with a few dictionaries and modifying dictionaries. Is there a way to format a dictionary for the log file so that it shows up as one block rather than a line?
I've gone through a bunch of simpler formatting attempts and read through How to insert newline in python logging?. Before I try writing a custom formatter just for dictionaries, wanted to find out if there's a known way to do this. Thanks!
The desired output would be something like this:
2024-02-13 13:27:03,685 [DEBUG] root: shelf_name = 'some shelf',
url = 'http://a_url',
creation_date = '02/12/2024'
2024-02-13 13:34:55,889 [DEBUG] root:
So is there any way to do this for a dictionary block?
UPDATED: Removed the old extraneous iterations. I'm posting the closest acceptable result, but still would like to make the dictionary print as a single block
class Downloader:
def __init__(self, shelf_data) -> None:
shelf = ShelfData(shelf_data)
[logging.debug(f"shelf['{key}']: {val}") for key, val in shelf.__dict__.items()]
Log file:
2024-02-13 16:29:18,024 [DEBUG] root: shelf['shelf_name']: test_shelf
2024-02-13 16:29:18,024 [DEBUG] root: shelf['url']: https://site/group/show/1865-scifi-and-fantasy-book-club
2024-02-13 16:29:18,024 [DEBUG] root: shelf['base_path']: C:\MyProjects\downloads
2024-02-13 16:29:18,024 [DEBUG] root: shelf['creation_date']: 02/12/2024
2024-02-13 16:29:18,039 [DEBUG] root: shelf['sort_order']: descend
2024-02-13 16:29:18,039 [DEBUG] root: shelf['books_per_page']: 100
2024-02-13 16:29:18,039 [DEBUG] root: shelf['download_dir']: None
2024-02-13 16:29:18,039 [DEBUG] root: shelf['book_count']: 37095
2024-02-13 16:29:18,039 [DEBUG] root: shelf['page_count']: 371
Also, might as well add my logger:
logging_config = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
},
},
'handlers': {
'default_handler': {
'class': 'logging.FileHandler',
'level': 'DEBUG',
'formatter': 'standard',
'filename': os.path.join('logs', f'{log_name}.log'),
'encoding': 'utf-8'
},
'stream_handler': {
'class': 'logging.StreamHandler',
'level': 'DEBUG',
'formatter': 'standard',}
},
'loggers': {
'': {
'handlers': ['default_handler', 'stream_handler'],
'level': 'DEBUG',
'propagate': False
}
}
}
logging.config.dictConfig(logging_config)
Is there a way to format a dictionary for the log file so that it shows up as one block rather than a line?
You might implement own subclass of collections.UserDict
which would have own way of formatting for printing, consider following simple example
import collections
import logging
class MultiLineDict(collections.UserDict):
def __str__(self):
return "\n".join(f"{k} = {v}" for k, v in self.data.items())
dct = {"Able":1,"Baker":2,"Charlie":3}
mldct = MultiLineDict(dct)
logging.error(mldct)
giving
ERROR:root:Able = 1
Baker = 2
Charlie = 3
Observe that instances of MultiLineDict
does behave exactly like vanilla dict
except for formatting for output. That being said I discourage usage of own ad-hoc format, but rather choose one developed already, your desired result
2024-02-13 13:27:03,685 [DEBUG] root: shelf_name = 'some shelf',
url = 'http://a_url',
creation_date = '02/12/2024'
looks for me akin to TOML, but with single quotes rather than double quote