logging.config — Configuração do módulo logging¶
Código-fonte: Lib/logging/config.py
Esta seção descreve a API para configuração do módulo logging.
Funções de configuração¶
As funções a seguir configuram o módulo logging. Elas estão localizadas no módulo logging.config. Seu uso é opcional — você pode configurar o módulo logging usando essas funções ou fazendo chamadas para a API principal (definido no próprio logging) e definindo manipuladores que são declarados em logging ou em logging.handlers.
- logging.config.dictConfig(config)¶
Obtém a configuração de logging de um dicionário. Os conteúdos desse dicionário estão descritos abaixo em Esquema do Dicionário de Configuração.
Se um erro for encontrado durante a configuração, esta função levantará uma exceção
ValueError,TypeError,AttributeErrorouImportErrorcom uma mensagem adequadamente descritiva. A seguir está uma lista (possivelmente incompleta) de condições que levantarão um erro:Um
levelque não seja uma string ou que seja uma string que não corresponda a um nível de logging atualUm valor
propagateque não seja um booleano.Um id que não tenha um destino correspondente.
Um id de manipulador inexistente encontrado durante uma chamada incremental.
Um nome de registrador inválido.
Incapacidade de resolver para um objeto interno ou externo.
A análise é realizada pela classe
DictConfigurator, cujo construtor recebe o dicionário usado para a configuração e possui um métodoconfigure(). O módulologging.configtem um atributo chamáveldictConfigClassque é inicialmente definido comoDictConfigurator. Você pode substituir o valor dedictConfigClasspor uma implementação adequada de sua autoria.A função
dictConfig()chamadictConfigClasspassando o dicionário especificado e, em seguida, chama o métodoconfigure()no objeto devolvido para colocar a configuração em efeito:def dictConfig(config): dictConfigClass(config).configure()
Por exemplo, uma subclasse de
DictConfiguratorpoderia chamarDictConfigurator.__init__()no seu próprio__init__(), em seguida, configurar prefixos personalizados que seriam utilizáveis na chamadaconfigure()subsequente.dictConfigClassseria ligado a esta nova subclasse, e entãodictConfig()poderia ser chamado exatamente como no estado padrão, sem personalização.Adicionado na versão 3.2.
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)¶
Lê a configuração de logging de um arquivo no formato
configparser. O formato do arquivo deve ser como descrito em Formato do arquivo de configuração. Esta função pode ser chamada várias vezes a partir de uma aplicação, permitindo que um usuário final selecione entre várias configurações pré-prontas (se o desenvolvedor fornecer um mecanismo para apresentar as escolhas e carregar a configuração escolhida).A função levantará uma exceção
FileNotFoundErrorse o arquivo não existir eRuntimeErrorse o arquivo for inválido ou vazio.- Parâmetros:
fname – Um nome de arquivo, ou um objeto arquivo, ou uma instância derivada de
RawConfigParser. Se uma instância derivada deRawConfigParserfor passada, ela é usada como está. Caso contrário, uma instância deConfigParseré criada, e a configuração é lida por ela a partir do objeto passado emfname. Se esse objeto tiver um métodoreadline(), ele é presumido como um objeto arquivo ou similar e lido usandoread_file(); caso contrário, é presumido como um nome de arquivo e passado pararead().defaults – Os defaults a serem passados para o
ConfigParserpodem ser especificados nesse argumento.disable_existing_loggers – Se especificado como
False, os registradores que existem quando esta chamada é feita são deixados habilitados. O padrão éTrueporque isso habilita o comportamento antigo de forma retrocompatível. Este comportamento é para desabilitar quaisquer registradores não-raiz existentes, a menos que eles ou seus ancestrais sejam explicitamente nomeados na configuração de logging.encoding – A codificação usada para abrir o arquivo quando fname é um nome de arquivo.
Alterado na versão 3.4: Uma instância de uma subclasse de
RawConfigParseragora é aceita como um valor parafname. Isso facilita:Uso de um arquivo de configuração onde a configuração de logging é apenas parte da configuração geral da aplicação.
Uso de uma configuração lida de um arquivo, e então modificada pela aplicação que a usa (por exemplo, baseada em parâmetros de linha de comando ou outros aspectos do ambiente de tempo de execução) antes de ser passada para
fileConfig.
Alterado na versão 3.10: Adicionado o parâmetro encoding.
Alterado na versão 3.12: Uma exceção será levantada se o arquivo fornecido não existir ou for inválido ou for vazio.
- logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)¶
Inicia um servidor soquete na porta especificada e escuta por novas configurações. Se nenhuma porta for especificada, o padrão do módulo
DEFAULT_LOGGING_CONFIG_PORTé usado. As configurações de logging serão enviadas como um arquivo adequado para processamento pordictConfig()ou porfileConfig(). Retorna uma instância deThreadna qual você pode chamarstart()para iniciar o servidor, e à qual você podejoin()quando apropriado. Para interromper o servidor, chamestopListening().O argumento
verify, se especificado, deve ser um chamável que verifique se os bytes recebidos através do soquete são válidos e devem ser processados. Isso pode ser feito criptografando e/ou assinando o que é enviado através do soquete, de modo que o chamávelverifypossa realizar a verificação de assinatura e/ou a descriptografia. O chamávelverifyé chamado com um único argumento – os bytes recebidos através do soquete – e deve retornar os bytes a serem processados, ouNonepara indicar que os bytes devem ser descartados. Os bytes devolvidos podem ser os mesmos que os bytes passados (por exemplo, quando apenas a verificação é feita), ou podem ser completamente diferentes (talvez se a descriptografia for realizada).Para enviar uma configuração para o soquete, leia o arquivo de configuração e o envie para o soquete como uma sequência de bytes precedida por uma string de comprimento de quatro bytes empacotada em binário usando
struct.pack('>L', n).Nota
Because portions of the configuration are passed through
eval(), use of this function may open its users to a security risk. While the function only binds to a socket onlocalhost, and so does not accept connections from remote machines, there are scenarios where untrusted code could be run under the account of the process which callslisten(). Specifically, if the process callinglisten()runs on a multi-user machine where users cannot trust each other, then a malicious user could arrange to run essentially arbitrary code in a victim user’s process, simply by connecting to the victim’slisten()socket and sending a configuration which runs whatever code the attacker wants to have executed in the victim’s process. This is especially easy to do if the default port is used, but not hard even if a different port is used. To avoid the risk of this happening, use theverifyargument tolisten()to prevent unrecognised configurations from being applied.Alterado na versão 3.4: O argumento
verifyfoi adicionado.Nota
Se você deseja enviar configurações para o listener que não desabilitem os registradores existentes, você precisará usar um formato JSON para a configuração, que usará
dictConfig()para configuração. Este método permite que você especifiquedisable_existing_loggerscomoFalsena configuração que você envia.
Considerações de segurança¶
A funcionalidade de configuração de logging tenta oferecer conveniência, e em parte isso é feito ao oferecer a capacidade de converter texto presente em arquivos de configuração em objetos Python usados na configuração de logging — por exemplo, conforme descrito em Objetos definidos pelo usuário. No entanto, esses mesmos mecanismos (importar chamáveis de módulos definidos pelo usuário e chamá-los com parâmetros da configuração) poderiam ser usados para invocar qualquer código que você desejar, e por essa razão você deve tratar arquivos de configuração de fontes não confiáveis com extrema cautela e certificar-se de que nada de ruim pode acontecer se você carregá-los, antes de realmente carregá-los.
Esquema do Dicionário de Configuração¶
Descrever uma configuração de registrador requer listar os vários objetos a serem criados e as conexões entre eles; por exemplo, você pode criar um manipulador nomeado ‘console’ e, em seguida, dizer que o logger nomeado ‘startup’ enviará suas mensagens para o manipulador ‘console’. Estes objetos não se limitam àqueles fornecidos pelo módulo logging, pois você pode escrever sua própria classe de formatador ou de manipulador. Os parâmetros para essas classes também podem precisar incluir objetos externos, como sys.stderr. A sintaxe para descrever esses objetos e conexões é definida abaixo em Conexões de objeto.
Detalhes do Esquema de Dicionário¶
O dicionário passado para dictConfig() deve conter as chaves a seguir:
version - deve ser definido como um valor inteiro representando a versão do esquema. O único valor válido atualmente é 1, mas ter esta chave permite que o esquema evolua, preservando ainda a retrocompatibilidade.
Todas as outras chaves são opcionais, mas se estiverem presentes, serão interpretadas conforme descrito abaixo. Em todos os casos abaixo onde um ‘dicionário de configuração’ é mencionado, ele será verificado quanto à chave especial '()' para consultar se uma instanciação personalizada é necessária. Se for o caso, o mecanismo descrito em Objetos definidos pelo usuário abaixo é usado para criar uma instância; caso contrário, o contexto é usado para determinar o que instanciar.
formatters - o valor correspondente será um dicionário em que cada chave é um id de formatador e cada valor é um dicionário que descreve como configurar a instância correspondente de
Formatter.O dicionário de configuração é buscado pelas chaves opcionais a seguir que correspondem aos argumentos passados para criar um objeto
Formatter:formatdatefmtstylevalidate(desde a versão >=3.8)defaults(desde versão >=3.12)
Uma chave opcional
classindica o nome da classe do formatador (como um módulo pontilhado e nome da classe). Os argumentos de instanciação são os mesmos que paraFormatterportanto, esta chave é mais útil para instanciar uma subclasse personalizada de :Formatter. Por exemplo, a classe alternativa pode apresentar tracebacks de exceção em um formato expandido ou condensado. Se o seu formatter exigir chaves de configuração diferentes ou extras, você deve usar Objetos definidos pelo usuário.filters - o valor correspondente será um dicionário no qual cada chave é um id de filter e cada valor é um dicionário que descreve como configurar a instância Filter correspondente.
O dicionário de configuração é pesquisado pela chave
name(que assume como padrão a string vazia) e esta é usada para construir uma instância delogging.Filter.handlers - o valor correspondente será um dicionário no qual cada chave é um id de manipulador e cada valor é um dicionário que descreve como configurar a instância de Manipulador correspondente.
O dicionário de configuração é pesquisado para as chaves a seguir:
class(obrigatório). Esse é o nome qualificado completo da classe do handler.level(opcional). O nível do manipulador.formatter(opcional). O id do formatador para esse manipulador.filters(opcional). Uma lista de ids dos filtros para esse manipulador.Alterado na versão 3.11:
filterspodem receber instâncias de filtro além de ids.
Todas as outras chaves são transmitidas como argumento nomeado para o construtor do manipulador. Por exemplo, dado o trecho:
handlers: console: class : logging.StreamHandler formatter: brief level : INFO filters: [allow_foo] stream : ext://sys.stdout file: class : logging.handlers.RotatingFileHandler formatter: precise filename: logconfig.log maxBytes: 1024 backupCount: 3
o manipulador com o id
consoleé instanciado como umlogging.StreamHandler, usandosys.stdoutcomo o fluxo subjacente. O manipulador com o idfileé instanciado como umlogging.handlers.RotatingFileHandlercom os argumentos nomeadosfilename='logconfig.log', maxBytes=1024, backupCount=3.loggers - o valor correspondente será um dicionário no qual cada chave é o nome de um registradores e cada valor é um dicionário que descreve como configurar a instância de Registrador correspondente.
O dicionário de configuração é pesquisado para as chaves a seguir:
level(opcional). O nível do registrador.propagate(opcional). A configuração de propagação do registrador.filters(opcional). Uma lista de ids dos filtros para esse registrador.Alterado na versão 3.11:
filterspodem receber instâncias de filtro além de ids.handlers(opcional). Uma lista de ids dos manipuladores para esse registrador.
Os registradores especificados serão configurados de acordo com o nível, a propagação, os filtros e os manipuladores especificados.
root - essa será a configuração para o registrador raiz. O processamento da configuração será igual ao de qualquer registrador, exceto pelo fato de que a configuração
propagatenão será aplicável.incremental - se a configuração deve ser interpretada como incremental à configuração existente. O padrão deste valor é
False, o que significa que a configuração especificada substitui a configuração existente com a mesma semântica usada pela configuração da API existentefileConfig().Se o valor especificado for
True, a configuração será processada conforme descrito na seção Configuração Incremental.disable_existing_loggers - se algum registrador não raiz existente deve ser desativado. Essa configuração reflete o parâmetro de mesmo nome em
fileConfig(). Se ausente, o padrão deste parâmetro éTrue. Este valor é ignorado se incremental forTrue.
Configuração Incremental¶
É difícil oferecer total flexibilidade para a configuração incremental. Por exemplo, como objetos, assim como filtros e formatadores, são anônimos, depois que uma configuração é definida, não é possível fazer referência a esse objeto anônimo ao ampliar uma configuração.
Além disso, não há um argumento convincente para alterar arbitrariamente o grafo de objetos de registradores, manipuladores, filtros e formatadores em tempo de execução, depois que uma configuração é definida; a verbosidade de registradores e manipuladores pode ser controlada simplesmente ajustando os níveis (e, no caso de registradores, os sinalizadores de propagação). Alterar o grafo de objetos arbitrariamente de forma segura é problemático em um ambiente multithread; embora não seja impossível, os benefícios não compensam a complexidade que isso acrescentaria à implementação.
Assim, quando a chave incremental de um dicionário de configuração estiver presente e for True, o sistema ignorará completamente quaisquer entradas formatters e filters, e processará apenas as configurações de level nas entradas handlers, e as configurações de level e propagate nas entradas loggers e root.
Usar um valor no dicionário de configuração permite que configurações sejam enviadas pela rede como dicionários pickled para um listener soquete. Assim, a verbosidade de registro de uma aplicação de longa execução pode ser alterada ao longo do tempo sem a necessidade de parar e reiniciar a aplicação.
Conexões de objeto¶
O esquema descreve um conjunto de objetos de logging — loggers, manipuladores, formatadores, filtros — que são conectados uns aos outros em um grafo de objetos. Assim, o esquema precisa representar conexões entre os objetos. Por exemplo, suponha que, após configurado, um determinado registrador tenha anexado a si um determinado manipulador. Para os propósitos desta discussão, podemos dizer que o registrador representa a origem e o manipulador o destino de uma conexão entre os dois. É claro que, nos objetos configurados, isso é representado pelo registrador mantendo uma referência ao manipulador. No dicionário de configuração, isso é feito atribuindo a cada objeto de destino um id que o identifica de forma inequívoca e, em seguida, usando esse id na configuração do objeto de origem para indicar que existe uma conexão entre o objeto de origem e o objeto de destino com aquele id.
Então, por exemplo, considere o seguinte trecho de YAML:
formatters:
brief:
# configuration for formatter with id 'brief' goes here
precise:
# configuration for formatter with id 'precise' goes here
handlers:
h1: #This is an id
# configuration of handler with id 'h1' goes here
formatter: brief
h2: #This is another id
# configuration of handler with id 'h2' goes here
formatter: precise
loggers:
foo.bar.baz:
# other configuration for logger 'foo.bar.baz'
handlers: [h1, h2]
(Observação: o YAML é usado aqui porque é um pouco mais legível do que o formulário de origem Python equivalente para o dicionário.)
Os ids para loggers são os nomes dos loggers que seriam usados programaticamente para obter uma referência a esses loggers, por exemplo, foo.bar.baz. Os ids para Formatadores e Filtros podem ser qualquer valor de string (como brief, precise acima) e são transitórios, no sentido de que só têm significado durante o processamento do dicionário de configuração e são usados para determinar conexões entre objetos, não sendo persistidos em nenhum lugar após a conclusão da chamada de configuração.
O trecho acima indica que o registrador nomeado foo.bar.baz deve ter dois manipuladores anexados a ele, que são descritos pelos IDs de manipulador h1 e h2. O formatador para h1 é o descrito pelo id brief, e o formatador para h2 é o descrito pelo id precise.
Objetos definidos pelo usuário¶
O esquema oferece suporte a objetos definidos pelo usuário para manipuladores, filtros e formatadores. (Os loggers não precisam ter tipos diferentes para instâncias diferentes, portanto este esquema de configuração não provê suporte às classes de registradores definidas pelo usuário.)
Objetos a serem configurados são descritos por dicionários que detalham sua configuração. Em alguns casos, o sistema de logging consegue inferir pelo contexto como um objeto deve ser instanciado, mas, quando se trata de um objeto definido pelo usuário, o sistema não saberá como fazer isso. Para oferecer total flexibilidade na instanciação desses objetos definidos pelo usuário, é necessário fornecer uma factory — um chamável que recebe um dicionário de configuração e retorna o objeto instanciado. Isso é sinalizado por um caminho de importação absoluto para a factory, disponibilizado sob a chave especial '()'. Aqui está um exemplo concreto:
formatters:
brief:
format: '%(message)s'
default:
format: '%(asctime)s %(levelname)-8s %(name)-15s %(message)s'
datefmt: '%Y-%m-%d %H:%M:%S'
custom:
(): my.package.customFormatterFactory
bar: baz
spam: 99.9
answer: 42
O trecho YAML acima define três formatadores. O primeiro, com id brief, é uma instância padrão de logging.Formatter com a string de formato especificado. O segundo, com id default, tem um formato mais longo e também define explicitamente o formato de tempo, e resultará em um logging.Formatter inicializado com essas duas strings de formatação. Em código-fonte Python, os formatadores brief e default têm subdicionários de configuração:
{
'format' : '%(message)s'
}
e:
{
'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
'datefmt' : '%Y-%m-%d %H:%M:%S'
}
respectivamente; e como esses dicionários não contêm a chave especial '()', a instanciação é inferida pelo contexto. Como resultado, são criadas instâncias padrão de logging.Formatter. O subdicionário de configuração do terceiro formatador, com o id custom, é:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42
}
and this contains the special key '()', which means that
user-defined instantiation is wanted. In this case, the specified
factory callable will be used. If it is an actual callable it will be
used directly - otherwise, if you specify a string (as in the example)
the actual callable will be located using normal import mechanisms.
The callable will be called with the remaining items in the
configuration sub-dictionary as keyword arguments. In the above
example, the formatter with id custom will be assumed to be
returned by the call:
my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)
Aviso
Os valores de chaves como bar, spam e answer no exemplo acima não devem ser dicionários de configuração nem referências como cfg://foo, ou ext://bar porque eles não serão processados pelo maquinário de configuração — serão simplesmente passados para a função callable como estão.
A chave '()' foi usada como chave especial porque não é um nome válido de parâmetro nomeado e, portanto, não conflita com os nomes dos argumentos nomeados usados na chamada. O '()' também serve como um mnemônico de que o valor correspondente é um chamável.
Alterado na versão 3.11: O membro filters de handlers e loggers pode receber instâncias de filtro, além de ids.
Você também pode especificar uma chave especial '.' cujo valor é um mapeamento de nomes de atributos para valores. Se essa chave for encontrada, os atributos especificados serão definidos no objeto definido pelo usuário antes que ele seja retornado. Assim, com a seguinte configuração:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42,
'.' {
'foo': 'bar',
'baz': 'bozz'
}
}
o formatador retornado terá o atributo foo definido como 'bar' e o atributo baz definido como 'bozz'.
Aviso
Os valores de atributos como foo e baz no exemplo acima não devem ser dicionários de configuração nem referências como cfg://foo ou ext://bar porque eles não serão processados pelo maquinário de configuração, mas definidos como valores de atributo exatamente como foram fornecidos.
Ordem de configuração de manipuladores¶
Handlers are configured in alphabetical order of their keys, and a configured
handler replaces the configuration dictionary in (a working copy of) the
handlers dictionary in the schema. If you use a construct such as
cfg://handlers.foo, then initially handlers['foo'] points to the
configuration dictionary for the handler named foo, and later (once that
handler has been configured) it points to the configured handler instance.
Thus, cfg://handlers.foo could resolve to either a dictionary or a handler
instance. In general, it is wise to name handlers in a way such that dependent
handlers are configured after any handlers they depend on; that allows
something like cfg://handlers.foo to be used in configuring a handler that
depends on handler foo. If that dependent handler were named bar,
problems would result, because the configuration of bar would be attempted
before that of foo, and foo would not yet have been configured.
However, if the dependent handler were named foobar, it would be configured
after foo, with the result that cfg://handlers.foo would resolve to
configured handler foo, and not its configuration dictionary.
Acesso a objetos externos¶
There are times where a configuration needs to refer to objects
external to the configuration, for example sys.stderr. If the
configuration dict is constructed using Python code, this is
straightforward, but a problem arises when the configuration is
provided via a text file (e.g. JSON, YAML). In a text file, there is
no standard way to distinguish sys.stderr from the literal string
'sys.stderr'. To facilitate this distinction, the configuration
system looks for certain special prefixes in string values and
treat them specially. For example, if the literal string
'ext://sys.stderr' is provided as a value in the configuration,
then the ext:// will be stripped off and the remainder of the
value processed using normal import mechanisms.
The handling of such prefixes is done in a way analogous to protocol
handling: there is a generic mechanism to look for prefixes which
match the regular expression ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$
whereby, if the prefix is recognised, the suffix is processed
in a prefix-dependent manner and the result of the processing replaces
the string value. If the prefix is not recognised, then the string
value will be left as-is.
Acesso a objetos internos¶
Além de objetos externos, às vezes também é necessário fazer referência a objetos na configuração. Isso será feito de forma implícita pelo sistema de configuração para coisas que ele conhece. Por exemplo, o valor em forma de string 'DEBUG' para um level em um logger ou manipulador será automaticamente convertido para o valor logging.DEBUG, e as entradas handlers, filters e formatter receberão um identificador de objeto e o resolverão para o objeto de destino apropriado.
However, a more generic mechanism is needed for user-defined
objects which are not known to the logging module. For
example, consider logging.handlers.MemoryHandler, which takes
a target argument which is another handler to delegate to. Since
the system already knows about this class, then in the configuration,
the given target just needs to be the object id of the relevant
target handler, and the system will resolve to the handler from the
id. If, however, a user defines a my.package.MyHandler which has
an alternate handler, the configuration system would not know that
the alternate referred to a handler. To cater for this, a generic
resolution system allows the user to specify:
handlers:
file:
# configuration of file handler goes here
custom:
(): my.package.MyHandler
alternate: cfg://handlers.file
A cadeia literal 'cfg://handlers.file' será resolvida de maneira análoga às strings com o prefixo ext:// mas procurando na própria configuração em vez do espaço de nomes de importação. O mecanismo permite acesso por ponto ou por índice, de forma semelhante ao que é fornecido por str.format. Assim, dado o seguinte trecho:
handlers:
email:
class: logging.handlers.SMTPHandler
mailhost: localhost
fromaddr: my_app@domain.tld
toaddrs:
- support_team@domain.tld
- dev_team@domain.tld
subject: Houston, we have a problem.
in the configuration, the string 'cfg://handlers' would resolve to
the dict with key handlers, the string 'cfg://handlers.email
would resolve to the dict with key email in the handlers dict,
and so on. The string 'cfg://handlers.email.toaddrs[1] would
resolve to 'dev_team@domain.tld' and the string
'cfg://handlers.email.toaddrs[0]' would resolve to the value
'support_team@domain.tld'. The subject value could be accessed
using either 'cfg://handlers.email.subject' or, equivalently,
'cfg://handlers.email[subject]'. The latter form only needs to be
used if the key contains spaces or non-alphanumeric characters. Please note
that the characters [ and ] are not allowed in the keys. If an
index value consists only of decimal digits, access will be attempted
using the corresponding integer value, falling back to the string
value if needed.
Dada uma string cfg://handlers.myhandler.mykey.123, ela será resolvida como config_dict['handlers']['myhandler']['mykey']['123']. Se a string for especificada como cfg://handlers.myhandler.mykey[123], o sistema tentará obter o valor de config_dict['handlers']['myhandler']['mykey'][123] e, caso isso falhe, recorrerá a config_dict['handlers']['myhandler']['mykey']['123'].
Resolução de importações e importadores personalizados¶
Import resolution, by default, uses the builtin __import__() function
to do its importing. You may want to replace this with your own importing
mechanism: if so, you can replace the importer attribute of the
DictConfigurator or its superclass, the
BaseConfigurator class. However, you need to be
careful because of the way functions are accessed from classes via
descriptors. If you are using a Python callable to do your imports, and you
want to define it at class level rather than instance level, you need to wrap
it with staticmethod(). For example:
from importlib import import_module
from logging.config import BaseConfigurator
BaseConfigurator.importer = staticmethod(import_module)
Você não precisa envolver com staticmethod() se estiver definindo o chamável de importação em uma instância do configurador.
Configurando QueueHandler e QueueListener¶
If you want to configure a QueueHandler, noting that this
is normally used in conjunction with a QueueListener, you
can configure both together. After the configuration, the QueueListener instance
will be available as the listener attribute of
the created handler, and that in turn will be available to you using
getHandlerByName() and passing the name you have used for the
QueueHandler in your configuration. The dictionary schema for configuring the pair
is shown in the example YAML snippet below.
handlers:
qhand:
class: logging.handlers.QueueHandler
queue: my.module.queue_factory
listener: my.package.CustomListener
handlers:
- hand_name_1
- hand_name_2
...
As chaves queue e listener são opcionais.
Se a chave queue estiver presente, o valor correspondente pode ser um dos seguintes:
An object implementing the
Queue.put_nowaitandQueue.getpublic API. For instance, this may be an actual instance ofqueue.Queueor a subclass thereof, or a proxy obtained bymultiprocessing.managers.SyncManager.Queue().É claro que isso só é possível se você estiver construindo ou modificando o dicionário de configuração no código.
Uma string que é resolvida para um chamável que, quando chamado sem argumentos, retorna a instância de fila a ser usada. Esse chamável pode ser uma subclasse de
queue.Queueou uma função que retorna uma instância de fila adequada, comomy.module.queue_factory().Um dicionário com a chave
'()'que é construído da forma usual discutida em Objetos definidos pelo usuário O resultado dessa construção deve ser uma instância dequeue.Queue.
Se a chave queue estiver ausente, uma instância padrão e não limitada de queue.Queue será criada e usada.
Se a chave listener estiver presente, o valor correspondente pode ser um dos seguintes:
Uma subclasse de
logging.handlers.QueueListener. Isso, naturalmente, só é possível se você estiver construindo ou modificando o dicionário de configuração em código.Uma string que é resolvida para uma classe que seja uma subclasse de
QueueListenercomo'my.package.CustomListener'.Um dicionário com a chave
'()', construído da maneira usual conforme discutido em Objetos definidos pelo usuário O resultado dessa construção deve ser um chamável com a mesma assinatura do inicializador deQueueListener.
Se a chave listener estiver ausente, será usada logging.handlers.QueueListener.
Os valores sob a chave handlers são os nomes de outros manipuladores na configuração (não mostrados no trecho acima) que serão passados ao queue listener.
Quaisquer classes personalizadas de manipulador de filas e de listener precisarão ser definidas com as mesmas assinaturas de inicialização que QueueHandler e QueueListener.
Adicionado na versão 3.12.
Formato do arquivo de configuração¶
The configuration file format understood by fileConfig() is based on
configparser functionality. The file must contain sections called
[loggers], [handlers] and [formatters] which identify by name the
entities of each type which are defined in the file. For each such entity, there
is a separate section which identifies how that entity is configured. Thus, for
a logger named log01 in the [loggers] section, the relevant
configuration details are held in a section [logger_log01]. Similarly, a
handler called hand01 in the [handlers] section will have its
configuration held in a section called [handler_hand01], while a formatter
called form01 in the [formatters] section will have its configuration
specified in a section called [formatter_form01]. The root logger
configuration must be specified in a section called [logger_root].
Nota
The fileConfig() API is older than the dictConfig() API and does
not provide functionality to cover certain aspects of logging. For example,
you cannot configure Filter objects, which provide for
filtering of messages beyond simple integer levels, using fileConfig().
If you need to have instances of Filter in your logging
configuration, you will need to use dictConfig(). Note that future
enhancements to configuration functionality will be added to
dictConfig(), so it’s worth considering transitioning to this newer
API when it’s convenient to do so.
Exemplos dessas seções no arquivo são fornecidos abaixo.
[loggers]
keys=root,log02,log03,log04,log05,log06,log07
[handlers]
keys=hand01,hand02,hand03,hand04,hand05,hand06,hand07,hand08,hand09
[formatters]
keys=form01,form02,form03,form04,form05,form06,form07,form08,form09
O logger raiz deve especificar um nível e uma lista de manipuladores. Um exemplo de seção de logger raiz é dado abaixo.
[logger_root]
level=NOTSET
handlers=hand01
The level entry can be one of DEBUG, INFO, WARNING, ERROR, CRITICAL or
NOTSET. For the root logger only, NOTSET means that all messages will be
logged. Level values are evaluated in the context of the logging
package’s namespace.
A entrada handlers é uma lista separada por vírgulas com os nomes dos manipuladores, que devem aparecer na seção [handlers]. Esses nomes precisam aparecer na seção [handlers] e ter seções correspondentes no arquivo de configuração.
Para loggers que não sejam o logger raiz, são necessárias algumas informações adicionais. Isso é ilustrado pelo exemplo a seguir.
[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser
The level and handlers entries are interpreted as for the root logger,
except that if a non-root logger’s level is specified as NOTSET, the system
consults loggers higher up the hierarchy to determine the effective level of the
logger. The propagate entry is set to 1 to indicate that messages must
propagate to handlers higher up the logger hierarchy from this logger, or 0 to
indicate that messages are not propagated to handlers up the hierarchy. The
qualname entry is the hierarchical channel name of the logger, that is to
say the name used by the application to get the logger.
As seções que especificam a configuração de manipuladores são exemplificadas pelo seguinte.
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)
A entrada class indica a classe do manipulador (conforme determinada por eval() no espaço de nomes do pacote logging). O level é interpretado da mesma forma que para loggers, e NOTSET é entendido como “registrar tudo”.
A entrada formatter indica o nome da chave do formatador para esse manipulador. Se estiver em branco, um formatador padrão (logging._defaultFormatter) será usado. Se um nome for especificado, ele deve aparecer na seção [formatters] e ter uma seção correspondente no arquivo de configuração.
The args entry, when evaluated in the context of the logging
package’s namespace, is the list of arguments to the constructor for the handler
class. Refer to the constructors for the relevant handlers, or to the examples
below, to see how typical entries are constructed. If not provided, it defaults
to ().
The optional kwargs entry, when evaluated in the context of the
logging package’s namespace, is the keyword argument dict to the constructor
for the handler class. If not provided, it defaults to {}.
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form02
args=('python.log', 'w')
[handler_hand03]
class=handlers.SocketHandler
level=INFO
formatter=form03
args=('localhost', handlers.DEFAULT_TCP_LOGGING_PORT)
[handler_hand04]
class=handlers.DatagramHandler
level=WARN
formatter=form04
args=('localhost', handlers.DEFAULT_UDP_LOGGING_PORT)
[handler_hand05]
class=handlers.SysLogHandler
level=ERROR
formatter=form05
args=(('localhost', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER)
[handler_hand06]
class=handlers.NTEventLogHandler
level=CRITICAL
formatter=form06
args=('Python Application', '', 'Application')
[handler_hand07]
class=handlers.SMTPHandler
level=WARN
formatter=form07
args=('localhost', 'from@abc', ['user1@abc', 'user2@xyz'], 'Logger Subject')
kwargs={'timeout': 10.0}
[handler_hand08]
class=handlers.MemoryHandler
level=NOTSET
formatter=form08
target=
args=(10, ERROR)
[handler_hand09]
class=handlers.HTTPHandler
level=NOTSET
formatter=form09
args=('localhost:9022', '/log', 'GET')
kwargs={'secure': True}
As seções que especificam a configuração do formatador são caracterizadas pelo seguinte.
[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter
The arguments for the formatter configuration are the same as the keys in the dictionary schema formatters section.
The defaults entry, when evaluated in the context of
the logging package’s namespace, is a dictionary of default values for
custom formatting fields. If not provided, it defaults to None.
Nota
Devido ao uso de eval() conforme descrito acima, há riscos de segurança potenciais decorrentes do uso de listen() para enviar e receber configurações por meio de soquetes. Os riscos se limitam a situações em que vários usuários sem confiança mútua executam código na mesma máquina; consulte a documentação de listen() para mais informações.
Ver também
- Módulo
logging Referência da API para o módulo de logging.
- Módulo
logging.handlers Tratadores úteis incluídos no módulo logging.