Python / Django: Unter Runserver bei der Konsole anmelden, unter Apache in der Datei anmelden

113

Wie kann ich Trace-Nachrichten an die Konsole senden (wie print), wenn ich meine Django-App unter ausführe manage.py runserver, aber diese Nachrichten an eine Protokolldatei senden lassen, wenn ich die App unter Apache ausführe?

Ich habe die Django-Protokollierung überprüft und obwohl ich von der Flexibilität und Konfigurierbarkeit für fortgeschrittene Anwendungen beeindruckt war, bin ich immer noch ratlos, wie ich mit meinem einfachen Anwendungsfall umgehen soll.

Justin Grant
quelle
1
Die einfachste Lösung besteht darin, unterschiedliche settings.py-Dateien für den Hauptserver und die Entwicklungsumgebung zu haben, siehe deploydjango.com/django_project_structure
Alex

Antworten:

84

Auf stderr gedruckter Text wird im Fehlerprotokoll von httpd angezeigt, wenn er unter mod_wsgi ausgeführt wird. Sie können entweder printdirekt oder loggingstattdessen verwenden.

print >>sys.stderr, 'Goodbye, cruel world!'
Ignacio Vazquez-Abrams
quelle
2
Es ist jedoch technisch gesehen kein gültiges WSGI und löst in strengeren Umgebungen Fehler aus.
Paul McMillan
13
Es ist überhaupt nichts Falsches daran, 'print' mit 'sys.stderr' zu verwenden, was WSGI betrifft, und es sollte keine Fehler auslösen.
Graham Dumpleton
Ich habe sys importiert, aber das scheint bei mir nicht zu funktionieren.
Hack-R
17
Dies funktioniert in Python 3 nicht. Schauen Sie hier . Sie brauchenprint("Goodbye cruel world!", file=sys.stderr)
Kardamom
103

Hier ist eine auf Django-Protokollierung basierende Lösung. Es verwendet die DEBUG-Einstellung, anstatt tatsächlich zu überprüfen, ob Sie den Entwicklungsserver ausführen oder nicht. Wenn Sie jedoch einen besseren Weg finden, dies zu überprüfen, sollte die Anpassung einfach sein.

LOGGING = {
    'version': 1,
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(message)s'
        },
    },
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/path/to/your/file.log',
            'formatter': 'simple'
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    }
}

if DEBUG:
    # make all loggers use the console.
    for logger in LOGGING['loggers']:
        LOGGING['loggers'][logger]['handlers'] = ['console']

Weitere Informationen finden Sie unter https://docs.djangoproject.com/de/dev/topics/logging/ .

m01
quelle
8
versuchen Sie auchLOGGING['loggers'][logger]['handlers'] += ['console']
Nir Levy
@ m01: Nachdem Sie dies in settings.py konfiguriert haben, wie können Sie dies zum Drucken verwenden? Danke
Niks Jain
Ich füge den Code aus meiner Antwort nach settings.pyunten in meine ein und setze ihn DEBUG = True(suche diese Einstellung oben in derselben Datei). Dann python manage.py runserverstarte ich von einem Terminal aus (Einzelheiten finden Sie in den Django-Dokumenten), und die Protokollmeldungen werden im Terminalfenster angezeigt. In der Produktion würde ich eine andere settings.py verwenden, wobei DEBUG = False- die Protokollnachrichten an gehen /path/to/your/file.log.
m01
Ihre Einkerbung bereitete mir Kopfschmerzen. Danke für die Info, es funktioniert!
Ioan
Vielen Dank! Ich habe einige Änderungen an der Einrückung vorgenommen, ich hoffe, es ist jetzt besser
m01
26

Sie können die Protokollierung in Ihrer settings.pyDatei konfigurieren .

Ein Beispiel:

if DEBUG:
    # will output to your console
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
    )
else:
    # will output to logging file
    logging.basicConfig(
        level = logging.DEBUG,
        format = '%(asctime)s %(levelname)s %(message)s',
        filename = '/my_log_file.log',
        filemode = 'a'
    )

Dies hängt jedoch von der Einstellung von DEBUG ab, und vielleicht möchten Sie sich keine Gedanken darüber machen müssen, wie es eingerichtet ist. Siehe diese Antwort unter Wie kann ich feststellen, ob meine Django-Anwendung auf einem Entwicklungsserver ausgeführt wird oder nicht? für eine bessere Art, diese Bedingung zu schreiben. Bearbeiten: Das obige Beispiel stammt aus einem Django 1.1-Projekt. Die Protokollierungskonfiguration in Django hat sich seit dieser Version etwas geändert.

Bennylope
quelle
Ich möchte mich nicht auf DEBUG verlassen. Ich würde mich lieber auf den Mechanismus zur Erkennung von Dev-Servern verlassen, der in diesem anderen Beitrag verlinkt ist. Der Erkennungsmechanismus des anderen Posts basiert jedoch auf dem Zugriff auf eine Anforderungsinstanz. Wie kann ich eine Anforderungsinstanz in settings.py abrufen?
Justin Grant
4

Ich benutze das:

logging.conf:

[loggers]
keys=root,applog
[handlers]
keys=rotateFileHandler,rotateConsoleHandler

[formatters]
keys=applog_format,console_format

[formatter_applog_format]
format=%(asctime)s-[%(levelname)-8s]:%(message)s

[formatter_console_format]
format=%(asctime)s-%(filename)s%(lineno)d[%(levelname)s]:%(message)s

[logger_root]
level=DEBUG
handlers=rotateFileHandler,rotateConsoleHandler

[logger_applog]
level=DEBUG
handlers=rotateFileHandler
qualname=simple_example

[handler_rotateFileHandler]
class=handlers.RotatingFileHandler
level=DEBUG
formatter=applog_format
args=('applog.log', 'a', 10000, 9)

[handler_rotateConsoleHandler]
class=StreamHandler
level=DEBUG
formatter=console_format
args=(sys.stdout,)

testapp.py:

import logging
import logging.config

def main():
    logging.config.fileConfig('logging.conf')
    logger = logging.getLogger('applog')

    logger.debug('debug message')
    logger.info('info message')
    logger.warn('warn message')
    logger.error('error message')
    logger.critical('critical message')
    #logging.shutdown()

if __name__ == '__main__':
    main()
xuejunliang
quelle
0

Sie können dies ziemlich einfach mit tagalog(https://github.com/dorkitude/tagalog) tun.

Während das Standard-Python-Modul beispielsweise in ein im Append-Modus geöffnetes Dateiobjekt schreibt, überschreibt das App Engine-Modul (https://github.com/dorkitude/tagalog/blob/master/tagalog_appengine.py) dieses Verhalten und verwendet es stattdessen logging.INFO.

Um dieses Verhalten in einem App Engine-Projekt zu erhalten, kann man einfach Folgendes tun:

import tagalog.tagalog_appengine as tagalog
tagalog.log('whatever message', ['whatever','tags'])

Sie können das Modul selbst erweitern und die Protokollfunktion ohne große Schwierigkeiten überschreiben.

Kyle Wild
quelle
0

Dies funktioniert in meiner local.py recht gut und erspart mir das Durcheinander bei der regulären Protokollierung:

from .settings import *

LOGGING['handlers']['console'] = {
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'verbose'
}
LOGGING['loggers']['foo.bar'] = {
    'handlers': ['console'],
    'propagate': False,
    'level': 'DEBUG',
}
jmoz
quelle