quelleck
quelleck

Reputation: 146

Python logs between multiple modules only work in functions called by original file?

I'm trying to add logging between a couple different modules. Why, when I place a log somewhere that isn't referenced in my original file, why does all logging break? I'm importing logging in both files. I import the other_file in file1.

Here is an example of what I'm running into with comments in other_file:

file1

import other_file

def main():
    logging.debug("Start")
    other_file.use_bar()
    logging.debug("End")

if __name__ == '__main__':
    import logging
    logging.basicConfig(filename='logfile.log',
                    level=logging.DEBUG,
                    format='%(asctime)s %(message)s',
                    datefmt='%m/%d/%Y %I:%M:%S %p')
    main()

other_file

import logging

def get_something():
    something = 'foo'
    # PUTTING A LOG HERE BREAKS ALL LOGS
    return something

bar = get_something()
# SO DOES PUTTING A LOG HERE

def use_bar():
    print(bar)
    logging.info("log bar")  # THIS LOG WORKS FINE

Upvotes: 1

Views: 155

Answers (2)

nsantana
nsantana

Reputation: 2050

What's the problem?

The function get_something is called before logging be configured. Then, it don't will appear on your logfile. This occur when you import the module other_file. Python automatically execute the function get_something and assign the result to variable bar. Take care on it.

bar = get_something()
# SO DOES PUTTING A LOG HERE

Suggested solution

To solve this problem, just assign the function get_something to bar, without call. Then, call bar() on function use_bar.

bar = get_something
# SO DOES PUTTING A LOG HERE

def use_bar():
    print(bar())
    logging.info("log bar")  # THIS LOG WORKS FINE

Complete Solution

main.py

import other_file
import logging  # Is recommend import modules on the top

def main():
    logging.debug("Start")
    other_file.use_bar()
    logging.debug("End")

if __name__ == '__main__':
    logging.basicConfig(filename='logfile.log',
                    level=logging.DEBUG,
                    format='%(asctime)s %(message)s',
                    datefmt='%m/%d/%Y %I:%M:%S %p')
    main()

other_file.py

import logging

def get_something():
    something = 'foo'
    # PUTTING A LOG HERE BREAKS ALL LOGS
    return something

bar = get_something
# SO DOES PUTTING A LOG HERE

def use_bar():
    print(bar())
    logging.info("log bar")  # THIS LOG WORKS FINE

Upvotes: 1

Ahmed Abdelkafi
Ahmed Abdelkafi

Reputation: 477

Your problem is related to how module import works in python.

Well, when importing the module other_file, Python automatically evaluates the line bar = set_something() by executing the function and store the result in bar and all of this is done before the logging starts. About putting a log in the line after bar = get_something() won't work because it'll be executed before the logging begins.

(I imagine that you'll need to use the value of bar to be global, if not, you can declare it inside the function use_bar() and in this case, the problem is solved.)

So the solution here might be replacing the line bar = get_something() by bar = get_something and now, bar is no longer a variable instead, Python will consider it as a function which is get_something and you can use it like : bar().

So if you want to preserve the same structure of your code, you have to change the other_file code as below :

other_file

import logging

def get_something():
    something = 'foo'
    # PUTTING A LOG HERE BREAKS ALL LOGS
    return something

bar = get_something

def use_bar():
    print(bar())
    logging.info("log bar")

But I suggest that you use this code instead which is (let's say) more pythonic :

file1

import logging
import other_file

def logger_config():
    logging.basicConfig(filename='logfile.log',
                        level=logging.DEBUG,
                        format='%(asctime)s %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p')
    return logging.getLogger(__name__)

def main():
    # Get the logger
    logger = logging.getLogger(__name__)
    logger.debug("Start")
    other_file.use_bar()
    logger.debug("End")

if __name__ == '__main__':
    main()

other_file

import logging

# Get the logger from the main module (file1)
logger = logging.getLogger(__name__)

def get_something():
    something = 'foo'
    # Your log here
    logger.info('Test log')
    return something

bar = get_something

def use_bar():
    print(bar())
    logger.info("log bar")

Upvotes: 1

Related Questions