I try to Implement an logger in Django. I had it allready working in Django Version 1.5 and Python 2.7.
But when I try to implement it on my actual Version(Django 2.0.8 and Python 3.6.5)
I get the Error on the following Code in the manage.py:
import logging.config
import os
import sys
PROJECT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(PROJECT_PATH)
os.environ["DJANGO_SETTINGS_MODULE"] = "ProjectServer.settings"
logging.config.fileConfig('ProjectServer/logging.ini')
try:
import settings
except ImportError:
import sys
sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing. ")
sys.exit(1)
if __name__ == "__main__":
import django
django.setup()
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
The Exception i get:
Exception has occurred: TypeError
'>' not supported between instances of 'str' and 'int'
File "C:\path\ProjectServer\manage.py", line 10, in<module>
logging.config.fileConfig('ProjectServer/logging.ini')
My logging.ini:
[loggers]
keys=root
[handlers]
keys=consoleHandler, rotatingFileHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=consoleHandler,rotatingFileHandler
[handler_consoleHandler]
class=logging.StreamHandler
level=INFO
formatter=simpleFormatter
args=(sys.stdout,)
[handler_rotatingFileHandler]
class=logging.handlers.RotatingFileHandler
args=(r'c:\log\debug.log','maxBytes=1000000','backupCount=3')
level=INFO
formatter=simpleFormatter
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
I don´t really get how it would come to the Error. When I checked the Pythonversion I didn´t notice any changes regarding the Logging.
Afterwards i´m importing the Logging and use it like this in my Models and Views
import logging
logger = logging.getLogger(__name__)
logger.info('error creating calendar file')
Operator > in python 2.7 can be used with two different types like string and integer. Example:
s = "xxx"
n = 123
s > n // will output True
In python3 this operation is not allowed.
TypeError: unorderable types: str() > int()
Comparison operator > is described in a detailed way in python docs
It seems that somewhere in your code you are trying to compare string vs integer.
EDIT (after OP posted the code)
The problem with operator > unsupported arguments occurs, because your RotatingFileHandler setting maxBytes is interpreted as a string instead of integer. You can fix this problem by providing the list of RotatingFileHandler constructor arguments without using keyword notation. Like this:
[handler_rotatingFileHandler]
class=logging.handlers.RotatingFileHandler
args=(r'c:\log\debug.log', 'a', 1000000, 3)
level=INFO
formatter=simpleFormatter
Second argument is mode and by default is equal to 'a'. reference
Related
I have configured logging in logging.config file. I have created a class where I access this configuration file, enable/disable the logger, and log some Info messages. I am importing this class in all the modules where I need to do some logging. When I try to log to a file, I get this error message. I am not able to understand what this error means.
File "/usr/local/lib/python3.6/configparser.py", line 959, in
getitem raise KeyError(key) KeyError: 'formatters'
logging.config
[loggers]
keys=root
[handlers]
keys=fileHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=INFO
handlers=fileHandler
[handler_fileHandler]
class=FileHandler
level=INFO
formatter=simpleFormatter
args=('example.log','a')
[formatter_simpleFormatter]
class=logging.Formatter
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
datefmt=
#Log.py
import logging.config
class Monitor(object):
fileName = path.join(path.split(path.dirname(path.abspath(__file__)))[0], "logging.config")
print (fileName) #prints /usr/local/lib/python3.6/site-packages/myproject-0.0.1-py3.6.egg/MyPackageName/logging.config
logging.config.fileConfig(fileName)
logger = logging.getLogger('root')
logger.disabled = False
#staticmethod
def Log(logMessage):
Monitor.logger.info(logMessage)
#sub.py
import Monitor
class Example
def simplelog(self,message):
Monitor.Log("Logging some message here")
#call some function here
Monitor.Log("Logging some other messages here for example")
I had similar issues when I tried to load config from a python script that was not on the project root directory. and what I figured out was that:
logging.config.fileConfig is dependent on configparser and have issues with initializing with absolute path. Try relative path.
Replace
fileName = path.join(path.split(path.dirname(path.abspath(__file__)))[0], "logging.config")
with some thing like:
## get path tree from project root and replace children from root with ".."
path_rslv = path.split(path.dirname(path.abspath(__file__)))[1:]
fileName = path.join(*[".." for dotdot in range(len(path_rslv)], "logging.config")
I have a logging.conf [1] file to configure the logging in my python application.
...
[handler_file_log_handler]
class=logging.handlers.TimedRotatingFileHandler
level=INFO
formatter=simple
args=('/var/log/myapp/myapp.log',)
As you can see, I'm storing the log file in /var/log/myapp directory.
What I would like is to store it in the user (the user that manages the application) home directory (/home/myuser/.myapp/log). So, my question is:
What should I configure in my logging.conf in order to be able to save the log file of my python application in the user home directory?
[1] - https://docs.python.org/2.6/library/logging.html#configuring-logging
Yes, you can pass any Python expression as argument! Including one that finds the user's home!
args=(f'{os.path.expanduser("~")}/myapp.log',)
For Python <= 3.5 (no f-strings):
args=(os.path.expanduser("~") + '/myapp.log',)
For completeness, here is a minimal example (tested with 3.5 and 3.9):
logging.conf
[loggers]
keys=root
[handlers]
keys=fileLogHandler
[formatters]
keys=simpleFormatter
[logger_root]
level=DEBUG
handlers=fileLogHandler
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
[handler_fileLogHandler]
class=logging.handlers.TimedRotatingFileHandler
formatter=simpleFormatter
args=(os.path.expanduser("~") + '/myapp.log',)
main.py
import logging
import logging.config
logging.config.fileConfig('logging.conf')
log = logging.getLogger(__name__)
log.info('Testo')
Additional note:
I thought that passing ~/myapp.log as path would work and let the OS take care of the expansion, which actually works in most places in Python. But inexplicably this does not work inside a logging.conf file!
args=('~/myapp.log',)
FileNotFoundError: [Errno 2] No such file or directory:
'/path/to/this/python/project/~/myapp.log' # ???
The user's home directory can be found (on any OS) using:
os.path.expanduser("~")
I am trying to enable my python logging using the following:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
import logging.config
import os
test_filename = 'my_log_file.txt'
try:
logging.config.fileConfig('loggingpy.conf', disable_existing_loggers=False)
except Exception as e:
# try to set up a default logger
logging.error("No loggingpy.conf to parse", exc_info=e)
logging.basicConfig(level=logging.WARNING, format="%(asctime)-15s %(message)s")
test1_log = logging.getLogger("test1")
test1_log.critical("test1_log crit")
test1_log.error("test1_log error")
test1_log.warning("test1_log warning")
test1_log.info("test1_log info")
test1_log.debug("test1_log debug")
I would like to use a loggingpy.conf file to control the logging like the following:
[loggers]
keys=root
[handlers]
keys=handRoot
[formatters]
keys=formRoot
[logger_root]
level=INFO
handlers=handRoot
[handler_handRoot]
class=FileHandler
level=INFO
formatter=formRoot
args=(test_filename,)
[formatter_formRoot]
format=%(asctime)s:%(name)s:%(process)d:%(lineno)d %(levelname)s %(message)s
datefmt=
class=logging.Formatter
Here I am trying to route the logging to the file named by the local "test_filename". When I run this, I get:
ERROR:root:No loggingpy.conf to parse
Traceback (most recent call last):
File "logging_test.py", line 8, in <module>
logging.config.fileConfig('loggingpy.conf', disable_existing_loggers=False)
File "/usr/lib/python2.7/logging/config.py", line 85, in fileConfig
handlers = _install_handlers(cp, formatters)
File "/usr/lib/python2.7/logging/config.py", line 162, in _install_handlers
args = eval(args, vars(logging))
File "<string>", line 1, in <module>
NameError: name 'test_filename' is not defined
CRITICAL:test1:test1_log crit
ERROR:test1:test1_log error
WARNING:test1:test1_log warning
Reading the docs, it seems that the "args" value in the config is eval'd in the context of the logging package namespace rather than the context when fileConfig is called. Is there any decent way to try to get the logging to behave this way through a configuration file so I can configure a dynamic log filename (usually like "InputFile.log"), but still have the flexibility to use the logging config file to change it?
Even though it's an old question, I think this still has relevance. An alternative to the above mentioned solutions would be to use logging.config.dictConfig(...) and manipulating the dictionary.
MWE:
log_config.yml
version: 1
disable_existing_loggers: false
formatters:
default:
format: "%(asctime)s:%(name)s:%(process)d:%(lineno)d %(levelname)s %(message)s"
handlers:
console:
class: logging.StreamHandler
formatter: default
stream: ext://sys.stdout
level: DEBUG
file:
class: logging.FileHandler
formatter: default
filename: "{path}/service.log"
level: DEBUG
root:
level: DEBUG
handlers:
- file
- console
example.py
import logging.config
import sys
import yaml
log_output_path = sys.argv[1]
log_config = yaml.load(open("log_config.yml"))
log_config["handlers"]["file"]["filename"] = log_config["handlers"]["file"]["filename"].format(path = log_output_path)
logging.config.dictConfig(log_config)
logging.debug("test")
Executable as follows:
python example.py .
Result:
service.log file in current working directory contains one line of log message.
Console outputs one line of log message.
Both state something like this:
2016-06-06 20:56:56,450:root:12232:11 DEBUG test
You could place the filename in the logging namespace with:
logging.test_filename = 'my_log_file.txt'
Then your existing loggingpy.conf file should work
You should be able to pollute the logging namespace with anything you like (within reason - i wouldn't try logging.config = 'something') in your module and that should make it referencable by the the config file.
The args statement is parsed using eval at logging.config.py _install_handlers. So you can add code into the args.
[handler_handRoot]
class=FileHandler
level=INFO
formatter=formRoot
args=(os.getenv("LOG_FILE","default_value"),)
Now you only need to populate the environment variable.
This is very hacky so I wouldn't recommend it. But if you for some reason did not want to add to the logging namespace you could pass the log file name through a command line argument and then use sys.argv[1] to access it (sys.argv[0] is the script name).
[handler_handRoot]
class=FileHandler
level=INFO
formatter=formRoot
args=(sys.argv[1],)
I want to write into two log files by using two loggers with following .ini config file:
[loggers]
keys=root,teja
[handlers]
keys=fileHandler,tejaFileHandler
[formatters]
keys=simpleFormatter
[logger_teja]
level=DEBUG
handlers=tejaFileHandler
qualname='tejaLogger'
[logger_root]
level=DEBUG
handlers=fileHandler
[handler_fileHandler]
class=logging.FileHandler
level=DEBUG
formatter=simpleFormatter
args=("error.log", "a")
[handler_tejaFileHandler]
class=logging.FileHandler
level=DEBUG
formatter=simpleFormatter
args=("teja.log", "a")
[formatter_simpleFormatter]
format=%(asctime)s - %(name)s - %(levelname)s - %(message)s
And I am using this configuration in my python code as
import logging
import logging.config
# load my module
import my_module
# load the logging configuration
logging.config.fileConfig('logging.ini')
logger1=logging.getLogger('root')
logger1.info('Hi how are you?')
logger2=logging.getLogger('teja')
logger2.debug('checking teja logger?')
I see that logs are written to error.log file whereas no logs are written to teja.log file. Please correct me if I am doing something silly...
You named your logger object 'tejaLogger':
[logger_teja]
level=DEBUG
handlers=tejaFileHandler
qualname='tejaLogger'
# ^^^^^^^^^^^^
Note that the quotes are part of the name.
but your test code picks up teja instead:
logger2=logging.getLogger('teja')
Rename one or the other; although you could use logging.getLogger("'tejaLogger'")
you probably want to drop the quotes and / or rename the logger to what you expected it to be:
[logger_teja]
level=DEBUG
handlers=tejaFileHandler
qualname=teja
It turns out that the problem is on this line (in the [logger_teja] section):
qualname='tejaLogger'
If you add this to your code (it prints all the current loggers):
print(logging.Logger.manager.loggerDict)
You get:
{"'tejaLogger'": <logging.Logger object at 0x7f89631170b8>}
Which means that your logger is called literally 'tejaLogger'. Using:
logger2=logging.getLogger("'tejaLogger'")`
Actually works fine. Either do that, or change qualname='tejaLogger' to qualname=teja.
I am planning to add logging mechanism in my python&geodjango web service.
Is there log4j look a like logging mechanism in python/geodjango?
I am looking for log4j's dailyrollingfileappender equivalent. Then automatically delete all 1month old log files.
Any guidance is appreciated.
UPDATES1
I am thinking of the below format.
datetime(ms)|log level|current thread name|client ip address|logged username|source file|source file line number|log message
Yes - Python 2.5 includes the 'logging' module. One of the handlers it supports is handlers.TimedRotatingFileHandler, this is what you're looking for. 'logging' is very easy to use:
example:
import logging
import logging.config
logging.fileConfig('mylog.conf')
logger = logging.getLogger('root')
The following is your config file for logging
#======================
# mylog.conf
[loggers]
keys=root
[handlers]
keys=default
[formatters]
keys=default
[logger_root]
level=INFO
handlers=default
qualname=(root) # note - this is used in non-root loggers
propagate=1 # note - this is used in non-root loggers
channel=
parent=
[handler_default]
class=handlers.TimedRotatingFileHandler
level=INFO
formatter=default
args=('try.log', 'd', 1)
[formatter_default]
format=%(asctime)s %(pathname)s(%(lineno)d): %(levelname)s %(message)s