Python / Django: accedi alla console sotto runserver, accedi al file sotto Apache


114

Come posso inviare messaggi di traccia alla console (come print) quando eseguo la mia app Django sotto manage.py runserver, ma avere quei messaggi inviati a un file di log quando eseguo l'app sotto Apache?

Ho esaminato il logging di Django e anche se sono rimasto impressionato dalla sua flessibilità e configurabilità per usi avanzati, sono ancora perplesso su come gestire il mio semplice caso d'uso.


1
La soluzione più semplice è avere file settings.py diversi per il server principale e l'ambiente di sviluppo, vedere deploydjango.com/django_project_structure
Alex

Risposte:


84

Il testo stampato su stderr verrà visualizzato nel registro degli errori di httpd durante l'esecuzione in mod_wsgi. Puoi usare printdirettamente o usare logginginvece.

print >>sys.stderr, 'Goodbye, cruel world!'

2
Tuttavia, tecnicamente non è un WSGI valido e attiverà errori in ambienti più rigidi.
Paul McMillan

13
Non c'è niente di sbagliato nell'usare 'print' con 'sys.stderr' per quanto riguarda WSGI e non dovrebbe causare errori.
Graham Dumpleton

Ho importato sys ma questo non sembra funzionare per me.
Hack-R

17
Questo non funziona in Python 3 dai un'occhiata qui . È necessarioprint("Goodbye cruel world!", file=sys.stderr)
cardamomo

103

Ecco una soluzione basata sulla registrazione di Django. Utilizza l'impostazione DEBUG invece di controllare effettivamente se stai eseguendo o meno il server di sviluppo, ma se trovi un modo migliore per verificarlo dovrebbe essere facile adattarlo.

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

vedere https://docs.djangoproject.com/en/dev/topics/logging/ per i dettagli.


8
prova ancheLOGGING['loggers'][logger]['handlers'] += ['console']
Nir Levy

@ m01: dopo averlo configurato in settings.py, come utilizzarlo per scopi di stampa? Grazie
Niks Jain

Ho inserito il codice dalla mia risposta nella mia settings.pyverso il basso e impostato DEBUG = True(cerca quell'impostazione vicino alla parte superiore nello stesso file). Quindi, corro python manage.py runserverda un terminale (vedi la documentazione di django per i dettagli) e i messaggi di log appariranno nella finestra del terminale. In produzione, userei un settings.py diverso, dove DEBUG = False- vanno i messaggi di log /path/to/your/file.log.
m01

La tua rientranza mi ha fatto venire il mal di testa. Grazie per le informazioni però, funziona!
ioan

Grazie! Ho apportato alcune modifiche al rientro, spero che sia meglio ora
m01

27

Puoi configurare la registrazione nel tuo settings.pyfile.

Un esempio:

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

Tuttavia dipende dall'impostazione di DEBUG e forse non vuoi preoccuparti di come è impostato. Vedi questa risposta su Come posso sapere se la mia applicazione Django è in esecuzione sul server di sviluppo o no? per un modo migliore di scrivere che condizionale. Modifica: l'esempio sopra è tratto da un progetto Django 1.1, la configurazione del log in Django è leggermente cambiata da quella versione.


Non voglio fare affidamento su DEBUG; Preferirei dipendere dal meccanismo di rilevamento del server di sviluppo collegato in quell'altro post. Ma il meccanismo di rilevamento dell'altro post si basa sull'accesso a un'istanza di richiesta. Come posso ottenere un'istanza di richiesta in settings.py?
Justin Grant

4

Io uso questo:

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

0

Puoi farlo abbastanza facilmente con tagalog(https://github.com/dorkitude/tagalog)

Ad esempio, mentre il modulo Python standard scrive su un oggetto file aperto in modalità di aggiunta, il modulo App Engine (https://github.com/dorkitude/tagalog/blob/master/tagalog_appengine.py) sovrascrive questo comportamento e invece utilizza logging.INFO.

Per ottenere questo comportamento in un progetto App Engine, si potrebbe semplicemente fare:

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

È possibile estendere il modulo da soli e sovrascrivere la funzione di registro senza troppe difficoltà.


0

Funziona abbastanza bene nel mio local.py, evitandomi di incasinare la registrazione regolare:

from .settings import *

LOGGING['handlers']['console'] = {
    'level': 'DEBUG',
    'class': 'logging.StreamHandler',
    'formatter': 'verbose'
}
LOGGING['loggers']['foo.bar'] = {
    'handlers': ['console'],
    'propagate': False,
    'level': 'DEBUG',
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.