getLogger(name) is typically executed. The getLogger() function accepts a single argument - the logger's name. It returns a reference to a logger instance with the specified name if provided, or root if not. Multiple calls to getLogger() with the same name will return a reference to the same logger object.
Python - Print Logs in a File. If you want to print python logs in a file rather than on the console then we can do so using the basicConfig() method by providing filename and filemode as parameter. The format of the message can be specified by using format parameter in basicConfig() method.
The correct answer for this is to use the already provided funcName
variable
import logging
logger = logging.getLogger(__name__)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)
logger.setLevel(logging.DEBUG)
Then anywhere you want, just add:
logger.debug('your message')
Example output from a script I'm working on right now:
[invRegex.py:150 - handleRange() ] ['[A-Z]']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03050>, '{', '1', '}']]
[invRegex.py:197 - handleMacro() ] ['\\d']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03950>, '{', '1', '}']]
[invRegex.py:210 - handleSequence() ] [[<__main__.GroupEmitter object at 0x10b9fedd0>, <__main__.GroupEmitter object at 0x10ba03ad0>]]
You have a few marginally related questions here.
I'll start with the easiest: (3). Using logging
you can aggregate all calls to a single log file or other output target: they will be in the order they occurred in the process.
Next up: (2). locals()
provides a dict of the current scope. Thus, in a method that has no other arguments, you have self
in scope, which contains a reference to the current instance. The trick being used that is stumping you is the string formatting using a dict as the RHS of the %
operator. "%(foo)s" % bar
will be replaced by whatever the value of bar["foo"]
is.
Finally, you can use some introspection tricks, similar to those used by pdb
that can log more info:
def autolog(message):
"Automatically log the current function details."
import inspect, logging
# Get the previous frame in the stack, otherwise it would
# be this function!!!
func = inspect.currentframe().f_back.f_code
# Dump the message + the name of this function to the log.
logging.debug("%s: %s in %s:%i" % (
message,
func.co_name,
func.co_filename,
func.co_firstlineno
))
This will log the message passed in, plus the (original) function name, the filename in which the definition appears, and the line in that file. Have a look at inspect - Inspect live objects for more details.
As I mentioned in my comment earlier, you can also drop into a pdb
interactive debugging prompt at any time by inserting the line import pdb; pdb.set_trace()
in, and re-running your program. This enables you to step through the code, inspecting data as you choose.
funcname
, linename
and lineno
provide information about the last function that did the logging.
If you have wrapper of logger (e.g singleton logger), then @synthesizerpatel's answer might not work for you.
To find out the other callers in the call stack you can do:
import logging
import inspect
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class MyLogger(metaclass=Singleton):
logger = None
def __init__(self):
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(threadName)s - %(message)s",
handlers=[
logging.StreamHandler()
])
self.logger = logging.getLogger(__name__ + '.logger')
@staticmethod
def __get_call_info():
stack = inspect.stack()
# stack[1] gives previous function ('info' in our case)
# stack[2] gives before previous function and so on
fn = stack[2][1]
ln = stack[2][2]
func = stack[2][3]
return fn, func, ln
def info(self, message, *args):
message = "{} - {} at line {}: {}".format(*self.__get_call_info(), message)
self.logger.info(message, *args)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With