Python / Django: registre no console no servidor de execução, registre no arquivo no Apache

113

Como posso enviar mensagens de rastreamento para o console (como print) quando estou executando meu aplicativo Django em manage.py runserver, mas essas mensagens são enviadas para um arquivo de log quando estou executando o aplicativo em Apache?

Eu revisei o log do Django e embora tenha ficado impressionado com sua flexibilidade e configurabilidade para usos avançados, ainda estou perplexo em como lidar com meu caso de uso simples.

Justin Grant
fonte
1
A solução mais simples é ter diferentes arquivos settings.py para o servidor principal e ambiente de desenvolvimento, consulte deploydjango.com/django_project_structure
Alex

Respostas:

84

O texto impresso em stderr aparecerá no log de erros do httpd quando executado em mod_wsgi. Você pode usar printdiretamente ou em loggingvez disso.

print >>sys.stderr, 'Goodbye, cruel world!'
Ignacio Vazquez-Abrams
fonte
2
No entanto, não é tecnicamente um WSGI válido e irá disparar erros em ambientes mais restritos.
Paul McMillan
13
Não há nada de errado em usar 'print' com 'sys.stderr' no que diz respeito ao WSGI e isso não deve causar erros.
Graham Dumpleton
Importei sys, mas isso não parece funcionar para mim.
Hack-R de
17
Isso não funciona no Python 3, dê uma olhada aqui . Você precisaprint("Goodbye cruel world!", file=sys.stderr)
cardamomo
103

Aqui está uma solução baseada em log do Django. Ele usa a configuração DEBUG em vez de realmente verificar se você está ou não executando o servidor de desenvolvimento, mas se você encontrar uma maneira melhor de verificar isso, será fácil de se adaptar.

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

consulte https://docs.djangoproject.com/en/dev/topics/logging/ para obter detalhes.

m01
fonte
8
também tenteLOGGING['loggers'][logger]['handlers'] += ['console']
Nir Levy
@ m01: Depois de configurar isso em settings.py, como usá-lo para fins de impressão? Obrigado
Niks Jain
Eu coloco o código da minha resposta na minha settings.pyparte inferior e a defino DEBUG = True(procure essa configuração perto da parte superior no mesmo arquivo). Então, eu corro python manage.py runserverde um terminal (veja a documentação do django para detalhes), e as mensagens de log aparecerão na janela do terminal. Na produção, eu usaria um settings.py diferente, para onde DEBUG = False- as mensagens de log vão /path/to/your/file.log.
m01,
Seu recuo me deu dor de cabeça. Obrigado pela informação, funciona!
Ioan
Obrigado! Fiz algumas alterações no recuo, espero que esteja melhor agora
m01
26

Você pode configurar o registro em seu settings.pyarquivo.

Um exemplo:

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

No entanto, isso depende da configuração de DEBUG e talvez você não queira se preocupar com a configuração. Veja esta resposta em Como posso saber se meu aplicativo Django está sendo executado no servidor de desenvolvimento ou não? para uma maneira melhor de escrever essa condicional. Editar: o exemplo acima é de um projeto Django 1.1, a configuração de registro no Django mudou um pouco desde essa versão.

bennylope
fonte
Não quero depender do DEBUG; Eu prefiro depender do mecanismo de detecção do dev-server vinculado naquele outro post. Mas o mecanismo de detecção da outra postagem depende de ter acesso a uma instância de solicitação. Como posso obter uma instância de solicitação em settings.py?
Justin Grant
4

Eu uso isso:

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
fonte
0

Você pode fazer isso facilmente com tagalog(https://github.com/dorkitude/tagalog)

Por exemplo, enquanto o módulo Python padrão grava em um objeto de arquivo aberto no modo anexar, o módulo do App Engine (https://github.com/dorkitude/tagalog/blob/master/tagalog_appengine.py) substitui esse comportamento e usa logging.INFO.

Para obter esse comportamento em um projeto do App Engine, pode-se simplesmente fazer:

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

Você mesmo pode estender o módulo e sobrescrever a função de log sem muita dificuldade.

Kyle Wild
fonte
0

Isso funciona muito bem no meu local.py, evitando que eu atrapalhe o registro regular:

from .settings import *

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