使用RotatingFileHandler控制日志文件的大小
# settings.py
LOGGING = {
...
'handlers': {
...
'file': {
'level': 'INFO',
'class': 'logging.RotatingFileHandler',
'filename': os.path.join(LOGS_DIR, 'app.log'),
'formatter': 'verbose',
'maxBytes': 1024,
'backupCount': 5
},
...
}
...
}
設置RotatingFileHandler的maxBytes與backupCount,這兩個參數默認是0。
當兩個參數都不為0時,會執行rallover過程:log文件大小接近maxBytes時,新建一個文件作為log的輸出,舊的文件會被加上類似'.1'、'.2'的后綴。
舉個例子,如果backupCount=5,log file定義的名字為app.log,你會得到app.log, app.log.1, app.log.2 一直到 app.log.5。
然而被寫入日志的永遠是app.log,寫滿了之后重命名為app.log.1,如果app.log.1存在,app.log.1會先被重名名為app.log.2,依此類推。
另外,如果app.log.5存在,它會被刪除。
windows環境遇到的問題
PermissionError: [WinError 32] 另一個程序正在使用此文件,進程無法訪問。
首先,Django默認啟用兩個進程,一個進程用來檢測文件變化,另一個進程是正經的服務器進程。settting.py這個文件被加載了兩次,也就是日志文件打開了兩次,如果是服務器進程先啟動,則看不出毛病來;如果是監控進程首先打開了從settings.py加載了日志,那么正經服務器進程就無法再次加載日志了。
如果你的Django項目是單進程的,那么在啟動Django項目的時候使用--noreload就可以解決
python manage.py runserver 0.0.0.0:80 --noreload
noreload表示不啟動Django的監控進程,也就是說項目代碼的改變不再會影響已經載入內存中的代碼,這樣,Django就只會起一個進程。
但是,如果你的項目是多進程的,或者在某些單獨的模塊,比如celery中為了使用Django的ORM而使用了django.setup()
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
import django
django.setup()
那么就需要用另一個日志模塊解決
pip install concurrent-log-handler
在LOGGING中,用concurrent_log_handler.ConcurrentRotatingFileHandler
代替logging.RotatingFileHandler
# settings.py
LOGGING = {
...
'handlers': {
...
'file': {
'level': 'INFO',
'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler',
'filename': os.path.join(LOGS_DIR, 'app.log'),
'formatter': 'verbose',
'maxBytes': 1024,
'backupCount': 5
},
...
}
...
}
測試一下,問題解決
另外,如果是linux系統下的多進程Django,可以用ConcurrentLogHandler模塊
pip install ConcurrentLogHandler
# settings.py
LOGGING = {
...
'handlers': {
...
'file': {
'level': 'INFO',
'class': 'cloghandler.ConcurrentRotatingFileHandler',
'filename': os.path.join(LOGS_DIR, 'app.log'),
'formatter': 'verbose',
'maxBytes': 1024,
'backupCount': 5
},
...
}
...
}