# 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。python
當兩個參數都不爲0時,會執行rallover過程:log文件大小接近maxBytes時,新建一個文件做爲log的輸出,舊的文件會被加上相似'.1'、'.2'的後綴。linux
舉個例子,若是backupCount=5,log file定義的名字爲app.log,你會獲得app.log, app.log.1, app.log.2 一直到 app.log.5。django
然而被寫入日誌的永遠是app.log,寫滿了以後重命名爲app.log.1,若是app.log.1存在,app.log.1會先被重名名爲app.log.2,依此類推。windows
另外,若是app.log.5存在,它會被刪除。bash
PermissionError: [WinError 32] 另外一個程序正在使用此文件,進程沒法訪問。
首先,Django默認啓用兩個進程,一個進程用來檢測文件變化,另外一個進程是正經的服務器進程。settting.py這個文件被加載了兩次,也就是日誌文件打開了兩次,若是是服務器進程先啓動,則看不出毛病來;若是是監控進程首先打開了從settings.py加載了日誌,那麼正經服務器進程就沒法再次加載日誌了。服務器
若是你的Django項目是單進程的,那麼在啓動Django項目的時候使用--noreload就能夠解決app
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()
那麼就須要用另外一個日誌模塊解決code
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 }, ... } ... }