Eu tenho um pequeno projeto python que tem a seguinte estrutura -
Project
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf
Planejo usar o módulo de log padrão para imprimir mensagens no stdout e em um arquivo de log. Para usar o módulo de log, é necessária alguma inicialização -
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')
logger.info('testing')
No momento, eu executo essa inicialização em todos os módulos antes de começar a registrar mensagens. É possível executar essa inicialização apenas uma vez em um local, para que as mesmas configurações sejam reutilizadas registrando-se em todo o projeto?
fileConfig
todos os módulos que efetuam log, a menos que tenhaif __name__ == '__main__'
lógica em todos eles. A resposta de prost não é uma boa prática se o pacote for uma biblioteca, embora possa funcionar para você - não se deve configurar o logon em pacotes da biblioteca, exceto adicionar aNullHandler
.package/__init__.py
. Normalmente, esse não é o lugar onde você coloca oif __name__ == '__main__'
código. Além disso, o exemplo de prost parece chamar o código de configuração incondicionalmente na importação, o que não parece correto para mim. Geralmente, o código de configuração de log deve ser feito em um único local e não deve ocorrer como efeito colateral da importação, exceto quando você estiver importando __main__.if __name__ == '__main__'
? (não é mencionada explicitamente em questão, se este for o caso)Respostas:
A melhor prática é, em cada módulo, ter um criador de logs definido assim:
próximo à parte superior do módulo e, em seguida, em outro código do módulo, por exemplo,
Se você precisar subdividir a atividade de log dentro de um módulo, use, por exemplo,
e faça logon
loggerA
eloggerB
conforme apropriado.No seu programa ou programas principais, faça, por exemplo:
ou
Veja aqui o log de vários módulos e aqui a configuração do log de código que será usado como um módulo de biblioteca por outro código.
Atualização: ao ligar
fileConfig()
, convém especificardisable_existing_loggers=False
se você está usando o Python 2.6 ou posterior (consulte os documentos para obter mais informações). O valor padrão éTrue
para compatibilidade com versões anteriores, que faz com que todos os criadores de logs existentes sejam desativados, afileConfig()
menos que eles ou seus ancestrais sejam explicitamente nomeados na configuração. Com o valor definido comoFalse
, os registradores existentes são deixados em paz. Se você estiver usando o Python 2.7 / Python 3.2 ou posterior, considere adictConfig()
API que é melhor dofileConfig()
que ela oferece mais controle sobre a configuração.fonte
disable_existing_loggers
bandeira que estáTrue
por padrão, mas pode ser configurada comoFalse
.Na verdade, cada criador de logs é filho do criador de pacotes dos pais (isto é,
package.subpackage.module
herda a configuração dopackage.subpackage)
, portanto, tudo o que você precisa fazer é apenas configurar o criador de logs raiz. Isso pode ser alcançado porlogging.config.fileConfig
(sua própria configuração para criadores delogging.basicConfig
logs) ou (define o criador de logs raiz) O log de instalação no seu módulo de entrada (__main__.py
ou o que você deseja executar, por exemplomain_script.py
.__init__.py
Também funciona)usando basicConfig:
usando fileConfig:
e crie cada registrador usando:
Para mais informações, consulte Tutorial Avançado de Log .
fonte
__main__.py
(por exemplo, se eu quiser usar o módulo em um script que não possua logger)logging.getLogger(__name__)
ainda fará algum tipo de logon no módulo ou isso criará uma exceção?Eu sempre faço isso como abaixo.
Use um único arquivo python para configurar meu log como padrão singleton chamado '
log_conf.py
'Em outro módulo, basta importar a configuração.
Este é um padrão único para registrar, de maneira simples e eficiente.
fonte
Várias dessas respostas sugerem que, no topo de um módulo, você faz
Entendo que isso seja considerado uma prática muito ruim . O motivo é que a configuração do arquivo desativará todos os registradores existentes por padrão. Por exemplo
E no seu módulo principal:
Agora, o log especificado em logging.ini estará vazio, pois o criador de logs existente foi desativado pela chamada fileconfig.
Embora seja certamente possível contornar isso (disable_existing_Loggers = False), realisticamente muitos clientes da sua biblioteca não saberão sobre esse comportamento e não receberão seus logs. Facilite para seus clientes sempre chamando logging.getLogger localmente. Dica: eu aprendi sobre esse comportamento no site de Victor Lin .
Portanto, é uma boa prática sempre chamar logging.getLogger localmente. Por exemplo
Além disso, se você usar fileconfig em seu diretório principal, defina disable_existing_loggers = False, caso seus designers de bibliotecas usem instâncias de registrador no nível do módulo.
fonte
logging.config.fileConfig('logging.ini')
antesimport my_module
? Como sugerido nesta resposta .logger = logging.getLogger(__name__)
'Uma maneira simples de usar uma instância da biblioteca de log em vários módulos para mim era a seguinte solução:
base_logger.py
Outros arquivos
fonte
Jogando em outra solução.
No init .py do meu módulo, tenho algo como:
Então, em cada módulo, preciso de um logger:
Quando os logs são perdidos, você pode diferenciar sua origem pelo módulo de origem.
fonte
Você também pode criar algo assim!
Agora você pode usar vários registradores no mesmo módulo e em todo o projeto, se o acima for definido em um módulo separado e importado em outros módulos onde o registro for necessário.
fonte
A solução da @ Yarkee parecia melhor. Gostaria de acrescentar algo a ele -
Portanto, o LoggerManager pode ser plugável em todo o aplicativo. Espero que faça sentido e valor.
fonte
Existem várias respostas. acabei com uma solução semelhante, mas diferente, que faz sentido para mim, talvez faça sentido para você também. Meu objetivo principal era poder passar logs para manipuladores por nível (logs de nível de depuração para o console, avisos e acima para arquivos):
criou um bom arquivo utilitário chamado logger.py:
o flask.app é um valor codificado no balão. o criador de aplicativos está sempre começando com flask.app como o nome do módulo.
Agora, em cada módulo, eu posso usá-lo no seguinte modo:
Isso criará um novo log para "app.flask.MODULE_NAME" com o mínimo de esforço.
fonte
A melhor prática seria criar um módulo separadamente, que possui apenas um método cuja tarefa é atribuir um manipulador de logger ao método de chamada. Salve este arquivo como m_logger.py
Agora chame o método getlogger () sempre que necessário.
fonte
--debug
a opção no aplicativo e quer nível de registo conjunto em todos os madeireiros em seu aplicativo com base neste parâmetro ...get_logger(level=logging.INFO)
para retornar algum tipo de singleton; portanto, quando ele ligou pela primeira vez no aplicativo principal, inicializa o criador de logs e os manipuladores com o nível adequado e depois retorna o mesmologger
objeto para todos os outros métodos.Novo no python, então não sei se isso é aconselhável, mas funciona muito bem para não reescrever o clichê.
Seu projeto deve ter um init .py para que possa ser carregado como um módulo
sys._getframe(1)
sugestão vem daquiEm seguida, use seu logger em qualquer outro arquivo:
Ressalvas:
import [your module]
não funcionará:python -m [your module name].[your filename without .py]
__main__
, mas qualquer solução usando__name__
terá esse problema.fonte