Python / Django: zaloguj się do konsoli pod serwerem uruchomieniowym, zaloguj do pliku pod Apache

114

Jak mogę wysyłać komunikaty śledzenia do konsoli (na przykład print), gdy uruchamiam aplikację Django pod manage.py runserver, ale czy te komunikaty są wysyłane do pliku dziennika, gdy uruchamiam aplikację pod Apache?

Sprawdziliśmy rejestrowanie Django i mimo że był pod wrażeniem jego elastyczność i konfigurowalność dla zaawansowanych zastosowań, ja wciąż zastanawiał się, jak radzić sobie mój prosty przypadków użycia.

Justin Grant
źródło
1
Najprostszym rozwiązaniem jest posiadanie różnych plików settings.py dla głównego serwera i środowiska programistycznego, patrz deploydjango.com/django_project_structure
Alex

Odpowiedzi:

84

Tekst drukowany na stderr pojawi się w dzienniku błędów httpd podczas pracy pod mod_wsgi. Możesz użyć printbezpośrednio lub loggingzamiast tego.

print >>sys.stderr, 'Goodbye, cruel world!'
Ignacio Vazquez-Abrams
źródło
2
Nie jest to jednak technicznie poprawny WSGI i będzie powodować błędy w bardziej rygorystycznych środowiskach.
Paul McMillan,
13
Nie ma nic złego w używaniu 'print' z 'sys.stderr' jeśli chodzi o WSGI i nie powinno to powodować błędów.
Graham Dumpleton
Zaimportowałem sys, ale wydaje mi się, że to nie działa.
Hack-R
17
To nie działa w Pythonie 3, spójrz tutaj . Potrzebujeszprint("Goodbye cruel world!", file=sys.stderr)
kardamon
103

Oto rozwiązanie oparte na logowaniu Django. Używa ustawienia DEBUG zamiast faktycznie sprawdzać, czy używasz serwera deweloperskiego, ale jeśli znajdziesz lepszy sposób, aby to sprawdzić, powinno być łatwe do dostosowania.

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']

szczegółowe informacje można znaleźć pod adresem https://docs.djangoproject.com/en/dev/topics/logging/ .

m01
źródło
8
spróbuj takżeLOGGING['loggers'][logger]['handlers'] += ['console']
Nir Levy
@ m01: Po skonfigurowaniu tego w settings.py, jak używać tego do celów drukowania? Dzięki
Niks Jain
Umieściłem kod z mojej odpowiedzi w mojej settings.pyna dole i ustawiłem DEBUG = True(szukaj tego ustawienia u góry w tym samym pliku). Następnie uruchamiam python manage.py runserverz terminala (szczegóły w dokumentacji django), a komunikaty dziennika pojawią się w oknie terminala. W produkcji użyłbym innego settings.py, gdzie DEBUG = False- wiadomości dziennika trafiają /path/to/your/file.log.
m01
Twoje wgłębienie przyprawiło mnie o ból głowy. Dzięki za informację, działa!
ioan
Dzięki! Zrobiłem kilka zmian w wcięciu, mam nadzieję, że teraz jest lepiej
m01
27

Możesz skonfigurować logowanie w swoim settings.pypliku.

Jeden przykład:

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'
    )

Zależy to jednak od ustawienia DEBUG i może nie chcesz martwić się o to, jak to jest skonfigurowane. Zobacz odpowiedź na temat Jak mogę sprawdzić, czy moja aplikacja Django działa na serwerze deweloperskim, czy nie? aby uzyskać lepszy sposób pisania tego warunku. Edycja: powyższy przykład pochodzi z projektu Django 1.1, konfiguracja logowania w Django zmieniła się nieco od tej wersji.

bennylope
źródło
Nie chcę polegać na DEBUG; Wolałbym polegać na mechanizmie wykrywania serwera deweloperskiego, o którym mowa w tym innym poście. Jednak mechanizm wykrywania drugiego posta polega na dostępie do instancji żądania. Jak mogę uzyskać instancję żądania w settings.py?
Justin Grant
4

Używam tego:

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
źródło
0

Możesz to zrobić całkiem łatwo za pomocą tagalog(https://github.com/dorkitude/tagalog)

Na przykład, podczas gdy standardowy moduł Pythona zapisuje do obiektu pliku otwartego w trybie dołączania, moduł App Engine (https://github.com/dorkitude/tagalog/blob/master/tagalog_appengine.py) zastępuje to zachowanie i zamiast tego używa logging.INFO.

Aby uzyskać takie zachowanie w projekcie App Engine, można po prostu:

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

Możesz samodzielnie rozszerzyć moduł i nadpisać funkcję dziennika bez większych trudności.

Kyle Wild
źródło
0

Działa to całkiem dobrze w moim local.py, oszczędza mi bałaganu podczas regularnego logowania:

from .settings import *

LOGGING['handlers']['console'] = {
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'verbose'
}
LOGGING['loggers']['foo.bar'] = {
    'handlers': ['console'],
    'propagate': False,
    'level': 'DEBUG',
}
jmoz
źródło