'Why logging works in a single call but not from main function?
I have a function called setup_logger() that sets up the logging system for my application, and it's located in the controllers.py file.
It works pretty well. But sometimes the logging is not being called when I run the functions from main.py (I'm using asyncio for some functions).
When I call my function get_browser() itself, the logging works and sends the message to StreamHandler and FileHandler as it is supposed to do.
But when I call this same function get_browser() from my file main.py, the logging doesn't do anything.
I'd like to know what could be stopping the logging function from being called, if it's the asyncio or something else.
My repo: https://github.com/guimatheus92/Bot_BombCrypto
My project:
└── Project
├── main.py # setup our app
├── controllers.py # this file contains setup_logger() and get_browser()
get_browser() function:
def get_browser():
logger = setup_logger(telegram_integration=True)
logger.info("Profiles selected: ...")
applications = []
website_browser = []
return applications, website_browser
setup_logger() function:
def setup_logger(telegram_integration=False, bot_name=''):
if bot_name != '':
formatter = logging.Formatter('%(levelname)s | Function: %(funcName)s | %(asctime)s: Bot (' + str(bot_name) + '): %(message)s', datefmt='%m/%d/%Y %H:%M:%S')
else:
formatter = logging.Formatter('%(levelname)s | Function: %(funcName)s | %(asctime)s: %(message)s', datefmt='%m/%d/%Y %H:%M:%S')
level = logging.INFO
consolehandler = logging.StreamHandler(sys.stdout)
consolehandler.setFormatter(formatter)
logger = logging.getLogger('logs')
if logger.hasHandlers():
# Logger is already configured, remove all handlers
logger.handlers = []
else:
logger.setLevel(level)
logger.addHandler(consolehandler)
return logger
In the main.py I'm just calling:
applications, website_browser = get_browser()
async def main():
logger = setup_logger(telegram_integration=True)
logger.info('------------------- New Execution ----------------\n')
logger.info('Starting Bot..... Bot started!')
applications, website_browser = get_browser()
logger.info('Number of accounts that the bot will run: %s' % (len(applications)))
if __name__ == "__main__":
try:
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
except Exception as e:
print("Exception: " + str(e))
exit()
Solution 1:[1]
Ideally, logging facilities should only be configured once unless you can't afford a cold reload of your application.
Have you considered using the standard logging.config.dictConfig instead of all your setup_logger? Simply craft the dict config dynamically with whatever parameterization you need and issue the configuration once, even before starting the event loop. Later, get the configured logger directly with logging.getLogger
I think this would aid you organising your code.
class TelegramHandler(logging.Handler):
def __init__(self, bot_name=''):
super().__init__()
self.bot_name = bot_name
def emit(self, record):
message = self.format(record)
send_telegram_msg(message, self.bot_name)
def get_logging_cfg(telegram_integration=False, bot_name=''):
return {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'default': {
'format':
'%(levelname)s | Function: %(funcName)s | %(asctime)s: Bot (' + str(bot_name) + '): %(message)s'
if bot_name else
'%(levelname)s | Function: %(funcName)s | %(asctime)s: %(message)s',
'datefmt': '%m/%d/%Y %H:%M:%S',
},
},
'handlers': {
'file': {
'formatter': 'default',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': os.path.join(pathlib.Path(__file__).parent.resolve(), 'logs', 'myapp.log'),
'when': 'D',
},
'telegram': {
'formatter': 'default',
'class': 'import.path.to.you.module.TelegramHandler',
'bot_name': bot_name,
},
'null': {
'formatter': 'default',
'class': 'logging.handlers.NullHandler',
}
},
'loggers': {
'logs': {
'handlers':
(['file'] if create_logfiles else [])
+ (['telegram'] if telegram_integration and telegram_token else [])
}
},
'root': {
# consider something else, for the sake of the logging happening beyond your own code
'handlers': ['null'],
'level': 'INFO',
},
}
async def main():
logger = logging.getLogger('logs')
logger.info('start')
applications, website_browser = get_browser()
# ...
def get_browser():
logger = logging.getLogger('logs')
logger.info('whatever')
# ...
if __name__ == "__main__":
logging.config.dictConfig(
get_logging_cfg(
telegram_integration=True,
bot_name='foo',
)
)
loop = asyncio.get_event_loop()
loop.create_task(main())
loop.run_forever()
Bonus: use TimedRotatingFileHandler instead of all that manual path crafting.
Python's logging is a beautiful library, you'll be happier if you read its docs thoroughly
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
