logging.config
— Konfiguration av loggning¶
Källkod: Lib/logging/config.py
I det här avsnittet beskrivs API:et för konfiguration av loggmodulen.
Funktioner för konfiguration¶
Följande funktioner konfigurerar loggningsmodulen. De finns i modulen logging.config
. Användningen av dem är valfri — du kan konfigurera loggmodulen med hjälp av dessa funktioner eller genom att göra anrop till huvud-API:t (definierat i logging
själv) och definiera hanterare som deklareras antingen i logging
eller logging.handlers
.
- logging.config.dictConfig(config)¶
Hämtar loggningskonfigurationen från en ordbok. Innehållet i denna ordbok beskrivs i Schema för konfigurationsordbok nedan.
Om ett fel uppstår under konfigurationen kommer denna funktion att ge upphov till
ValueError
,TypeError
,AttributeError
ellerImportError
med ett lämpligt beskrivande meddelande. Följande är en (eventuellt ofullständig) lista över villkor som ger upphov till ett fel:En
level
som inte är en sträng eller som är en sträng som inte motsvarar en faktisk loggningsnivå.Ett
propagate
-värde som inte är en boolean.Ett id som inte har någon motsvarande destination.
Ett icke-existerande hanterar-id hittades under ett inkrementellt anrop.
Ett ogiltigt loggarnamn.
Oförmåga att bestämma sig för ett inre eller yttre objekt.
Parsningen utförs av klassen
DictConfigurator
, vars konstruktör får den ordbok som används för konfigurationen och har en metodconfigure()
. Modulenlogging.config
har ett anropbart attributdictConfigClass
som initialt är inställt påDictConfigurator
. Du kan ersätta värdet pådictConfigClass
med en egen lämplig implementation.dictConfig()
anropardictConfigClass
som skickar den angivna ordlistan, och anropar sedanconfigure()
-metoden på det returnerade objektet för att sätta konfigurationen i kraft:def dictConfig(config): dictConfigClass(config).configure()
Till exempel skulle en underklass till
DictConfigurator
kunna anropaDictConfigurator.__init__()
i sin egen__init__()
, och sedan ställa in anpassade prefix som skulle kunna användas i det efterföljandeconfigure()
-anropet.dictConfigClass
skulle bindas till denna nya underklass, och sedan skulledictConfig()
kunna anropas exakt som i standardtillståndet, utan anpassning.Tillagd i version 3.2.
- logging.config.fileConfig(fname, defaults=None, disable_existing_loggers=True, encoding=None)¶
Läser in loggningskonfigurationen från en fil i formatet
configparser
. Filens format bör vara det som beskrivs i Format för konfigurationsfil. Den här funktionen kan anropas flera gånger från en applikation, så att slutanvändaren kan välja mellan olika förinställda konfigurationer (om utvecklaren tillhandahåller en mekanism för att presentera alternativen och ladda den valda konfigurationen).Den ger upphov till
FileNotFoundError
om filen inte finns ochRuntimeError
om filen är ogiltig eller tom.- Parametrar:
fname – Ett filnamn, eller ett filliknande objekt, eller en instans härledd från
RawConfigParser
. Om enRawConfigParser
-deriverad instans skickas, används den som den är. Annars instansieras enConfigParser
och konfigurationen läses av den från objektet som passeras ifname
. Om det har enreadline()
-metod, antas det vara ett filliknande objekt och läses medread_file()
; annars antas det vara ett filnamn och skickas tillread()
.defaults – Standardvärden som ska skickas till
ConfigParser
kan anges i detta argument.disable_existing_loggers – Om det anges som ”False” kommer loggar som finns när anropet görs att vara aktiverade. Standardvärdet är
True
eftersom detta aktiverar gammalt beteende på ett bakåtkompatibelt sätt. Detta beteende är att inaktivera alla befintliga loggar som inte är rotloggar om inte de eller deras förfäder uttryckligen namnges i loggningskonfigurationen.encoding – Den kodning som används för att öppna filen när fname är filnamnet.
Ändrad i version 3.4: En instans av en underklass till
RawConfigParser
accepteras nu som ett värde förfname
. Detta underlättar:Användning av en konfigurationsfil där loggningskonfigurationen bara är en del av den övergripande applikationskonfigurationen.
Användning av en konfiguration som läses från en fil och sedan ändras av det användande programmet (t.ex. baserat på kommandoradsparametrar eller andra aspekter av körtidsmiljön) innan den skickas till
fileConfig
.
Ändrad i version 3.10: Parametern encoding har lagts till.
Ändrad i version 3.12: Ett undantag kommer att kastas om den angivna filen inte finns eller är ogiltig eller tom.
- logging.config.listen(port=DEFAULT_LOGGING_CONFIG_PORT, verify=None)¶
Startar upp en socket-server på den angivna porten och lyssnar efter nya konfigurationer. Om ingen port anges används modulens standard
DEFAULT_LOGGING_CONFIG_PORT
. Loggningskonfigurationer kommer att skickas som en fil som kan bearbetas avdictConfig()
ellerfileConfig()
. Returnerar enThread
-instans på vilken du kan anropastart()
för att starta servern, och som du kanjoin()
när det är lämpligt. För att stoppa servern, anropastopListening()
.Argumentet
verify
, om det specificeras, bör vara en anropbar funktion som verifierar om byte som tas emot via sockeln är giltiga och bör behandlas. Detta kan göras genom att kryptera och/eller signera det som skickas över sockeln, så att anropsbarnetverify
kan utföra signaturverifiering och/eller dekryptering. Anropsbarhetenverify
anropas med ett enda argument - de byte som mottagits över sockeln - och bör returnera de byte som skall behandlas, ellerNone
för att ange att byte skall kasseras. De returnerade bytena kan vara desamma som de överförda bytena (t.ex. när endast verifiering görs), eller så kan de vara helt annorlunda (kanske om dekryptering utförts).För att skicka en konfiguration till uttaget läser du in konfigurationsfilen och skickar den till uttaget som en sekvens av byte som föregås av en fyra byte lång sträng som packas binärt med hjälp av
struct.pack('>L', n)
.Anteckning
Eftersom delar av konfigurationen skickas genom
eval()
kan användning av denna funktion innebära en säkerhetsrisk för användaren. Även om funktionen endast binder till ett uttag pålocalhost
, och därför inte accepterar anslutningar från fjärranslutna maskiner, finns det scenarier där opålitlig kod kan köras under kontot för den process som anroparlisten()
. Om processen som anroparlisten()
körs på en fleranvändarmaskin där användarna inte kan lita på varandra, kan en illvillig användare ordna så att i princip godtycklig kod körs i en utsatt användares process, helt enkelt genom att ansluta till den utsatta användarenslisten()
-socket och skicka en konfiguration som kör den kod som angriparen vill ha körd i den utsatta användarens process. Detta är särskilt lätt att göra om standardporten används, men inte svårt även om en annan port används. För att undvika risken att detta händer, använd argumentetverify
tilllisten()
för att förhindra att konfigurationer som inte känns igen används.Ändrad i version 3.4: Argumentet
verify
har lagts till.Anteckning
Om du vill skicka konfigurationer till lyssnaren som inte inaktiverar befintliga loggar, måste du använda ett JSON-format för konfigurationen, som använder
dictConfig()
för konfigurationen. Med den här metoden kan du angedisable_existing_loggers
somFalse
i den konfiguration du skickar.
Överväganden om säkerhet¶
Loggningskonfigurationsfunktionaliteten försöker erbjuda bekvämlighet, och delvis görs detta genom att erbjuda möjligheten att konvertera text i konfigurationsfiler till Python-objekt som används i loggningskonfigurationen - till exempel enligt beskrivningen i Användardefinierade objekt. Samma mekanismer (importera anropbara objekt från användardefinierade moduler och anropa dem med parametrar från konfigurationen) kan dock användas för att anropa vilken kod som helst, och därför bör du behandla konfigurationsfiler från opålitliga källor med extrema försiktighet och försäkra dig om att inget dåligt kan hända om du läser in dem innan du faktiskt läser in dem.
Schema för konfigurationsordbok¶
För att beskriva en loggningskonfiguration måste du lista de olika objekt som ska skapas och kopplingarna mellan dem; du kan till exempel skapa en hanterare med namnet ”console” och sedan säga att loggern med namnet ”startup” ska skicka sina meddelanden till hanteraren ”console”. Dessa objekt är inte begränsade till dem som tillhandahålls av modulen logging
eftersom du kan skriva din egen formaterare eller hanterarklass. Parametrarna till dessa klasser kan också behöva inkludera externa objekt som sys.stderr
. Syntaxen för att beskriva dessa objekt och anslutningar definieras i Objektanslutningar nedan.
Dictionary Schema Detaljer¶
Den ordbok som skickas till dictConfig()
måste innehålla följande nycklar:
version - ska sättas till ett heltalsvärde som representerar schemaversionen. Det enda giltiga värdet för närvarande är 1, men genom att ha denna nyckel kan schemat utvecklas samtidigt som bakåtkompatibiliteten bevaras.
Alla andra nycklar är valfria, men om de finns med tolkas de enligt beskrivningen nedan. I alla fall nedan där en ”configuring dict” nämns, kommer den att kontrolleras för den speciella nyckeln '()'
för att se om en anpassad instansiering krävs. Om så är fallet används den mekanism som beskrivs i Användardefinierade objekt nedan för att skapa en instans; annars används sammanhanget för att avgöra vad som ska instansieras.
formatters - motsvarande värde kommer att vara en dict där varje nyckel är ett formatter-id och varje värde är en dict som beskriver hur man konfigurerar motsvarande
Formatter
-instans.Konfigurationsdikten genomsöks efter följande valfria nycklar som motsvarar de argument som skickas för att skapa ett
Formatter
-objekt:format
datefmt
style
validate
(sedan version >=3.8)defaults
(sedan version >=3.12)
En valfri
class
-nyckel anger namnet på formaterarens klass (som en prickad modul och klassnamn). Instantieringsargumenten är desamma som förFormatter
, så den här nyckeln är mest användbar för instansiering av en anpassad underklass tillFormatter
. Den alternativa klassen kan t.ex. presentera spårningar av undantag i ett utökat eller förkortat format. Om din formatterare kräver andra eller extra konfigurationsnycklar bör du använda Användardefinierade objekt.filters - motsvarande värde kommer att vara en dikt där varje nyckel är ett filter-ID och varje värde är en dikt som beskriver hur man konfigurerar motsvarande filterinstans.
Konfigurationsdikten genomsöks efter nyckeln
name
(standard är den tomma strängen) och denna används för att konstruera enlogging.Filter
-instans.handlers - motsvarande värde kommer att vara ett dict där varje nyckel är ett handläggar-ID och varje värde är ett dict som beskriver hur man konfigurerar motsvarande handläggarinstans.
Konfigurationsdikten genomsöks efter följande nycklar:
class
(obligatorisk). Detta är det fullständigt kvalificerade namnet på hanterarklassen.level
(valfritt). Behandlarens nivå.formatter
(valfritt). ID för formateraren för den här hanteraren.filters
(valfritt). En lista med id:n för filtren för den här hanteraren.Ändrad i version 3.11:
filters
kan ta filterinstanser i tillägg till id:n.
Alla andra nycklar skickas som nyckelordsargument till hanterarens konstruktör. Till exempel, med tanke på utdraget:
handläggare: konsol: klass : loggning.StreamHandler formaterare: kort nivå: INFO filter: [allow_foo] ström : ext://sys.stdout fil : stdout klass : logging.handlers.RotatingFileHandler formaterare: exakt filnamn: logconfig.log maxBytes: 1024 backupCount: 3
hanteraren med id
console
instansieras som enlogging.StreamHandler
, medsys.stdout
som underliggande ström. Hanteraren med idfile
instansieras som enlogging.handlers.RotatingFileHandler`
med nyckelordsargumentenfilnamn='logconfig.log', maxBytes=1024, backupCount=3
.loggers - motsvarande värde kommer att vara ett dict där varje nyckel är ett loggernamn och varje värde är ett dict som beskriver hur man konfigurerar motsvarande Logger-instans.
Konfigurationsdikten genomsöks efter följande nycklar:
level
(valfritt). Loggarens nivå.propagate
(valfritt). Loggerns inställning för spridning.filters
(valfritt). En lista med id:n för filtren för den här loggern.Ändrad i version 3.11:
filters
kan ta filterinstanser i tillägg till id:n.handlers
(valfritt). En lista med id:n för handläggarna för denna logger.
De angivna loggarna kommer att konfigureras enligt den nivå, spridning, de filter och de hanterare som anges.
root - detta är konfigurationen för rotloggaren. Konfigurationen bearbetas på samma sätt som för alla loggar, förutom att inställningen
propagate
inte är tillämplig.incremental - om konfigurationen ska tolkas som inkrementell till den befintliga konfigurationen. Standardvärdet är
False
, vilket innebär att den angivna konfigurationen ersätter den befintliga konfigurationen med samma semantik som används av det befintliga API:etfileConfig()
.Om det angivna värdet är
True
bearbetas konfigurationen enligt beskrivningen i avsnittet om Inkrementell konfiguration.disable_existing_loggers - om alla befintliga loggar som inte är rotloggar ska inaktiveras. Denna inställning speglar parametern med samma namn i
fileConfig()
. Om parametern saknas är standardvärdetTrue
. Detta värde ignoreras om incremental ärTrue
.
Inkrementell konfiguration¶
Det är svårt att ge fullständig flexibilitet för inkrementell konfiguration. Eftersom objekt som filter och formatterare är anonyma är det till exempel inte möjligt att hänvisa till sådana anonyma objekt när en konfiguration har konfigurerats.
Det finns inte heller några övertygande skäl för att godtyckligt ändra objektgrafen för loggrar, hanterare, filter och formaterare under körning, när en konfiguration väl har skapats; ordrikedomen hos loggrar och hanterare kan styras genom att bara ange nivåer (och, när det gäller loggrar, spridningsflaggor). Att ändra objektgrafen godtyckligt på ett säkert sätt är problematiskt i en flertrådad miljö; även om det inte är omöjligt är fördelarna inte värda den komplexitet som det tillför implementeringen.
När nyckeln incremental
i en konfigurationsdikt är närvarande och är True
, kommer systemet att helt ignorera alla formatters
och filters
poster och endast bearbeta level
inställningarna i handlers
posterna, och level
och propagate
inställningarna i loggers
och root
posterna.
Genom att använda ett värde i konfigurationsdictet kan konfigurationer skickas över kabeln som pickled dicts till en socketlyssnare. På så sätt kan loggningsstyrkan i en applikation som körs under lång tid ändras över tid utan att applikationen behöver stoppas och startas om.
Objektanslutningar¶
Schemat beskriver en uppsättning loggningsobjekt - loggers, handlers, formatters, filters - som är kopplade till varandra i en objektgraf. Schemat måste alltså representera kopplingar mellan objekten. Låt oss till exempel säga att en viss logger har en viss hanterare kopplad till sig när den väl har konfigurerats. I den här diskussionen kan vi säga att loggern representerar källan och hanteraren destinationen för en koppling mellan de två. I de konfigurerade objekten representeras detta naturligtvis av att loggern har en referens till hanteraren. I konfigurationsdikten görs detta genom att ge varje destinationsobjekt ett id som identifierar det på ett otvetydigt sätt och sedan använda id:t i källobjektets konfiguration för att ange att det finns en koppling mellan källan och destinationsobjektet med det id:t.
Tänk till exempel på följande YAML-utdrag:
formatterare:
kort:
# konfigurationen för formatterare med id 'brief' hamnar här
exakt:
# konfiguration för formatterare med id 'precise' går här
hanterare:
h1: #Detta är ett id
# konfiguration av hanterare med id 'h1' går här
formatterare: kort
h2: #Detta är ett annat id
# konfiguration av hanterare med id 'h2' går här
formattering: exakt
loggers:
foo.bar.baz:
# annan konfiguration för logger 'foo.bar.baz'
handläggare: [h1, h2]
(Observera: YAML används här eftersom det är lite mer läsbart än motsvarande Python-källform för ordlistan)
Ids för loggers är de loggernamn som skulle användas programmatiskt för att få en referens till dessa loggers, t.ex. foo.bar.baz
. ID:n för Formatters och Filters kan vara vilket strängvärde som helst (t.ex. brief
, precise
ovan) och de är transienta, dvs. de är endast meningsfulla för bearbetning av konfigurationsordlistan och används för att fastställa kopplingar mellan objekt, och sparas inte någonstans när konfigurationsanropet är klart.
Ovanstående utdrag visar att loggern med namnet foo.bar.baz
ska ha två hanterare kopplade till sig, vilka beskrivs av hanterar-ID h1
och h2
. Formateringen för h1
är den som beskrivs av id brief
, och formateringen för h2
är den som beskrivs av id precise
.
Användardefinierade objekt¶
Schemat stöder användardefinierade objekt för hanterare, filter och formaterare. (Loggrar behöver inte ha olika typer för olika instanser, så det finns inget stöd i detta konfigurationsschema för användardefinierade loggerklasser)
Objekt som ska konfigureras beskrivs av ordböcker som beskriver deras konfiguration. På vissa ställen kan loggningssystemet dra slutsatser från sammanhanget om hur ett objekt ska instansieras, men när ett användardefinierat objekt ska instansieras vet systemet inte hur det ska göras. För att ge fullständig flexibilitet för instansiering av användardefinierade objekt måste användaren tillhandahålla en ”fabrik” - en anropsbar funktion som anropas med en konfigurationsordbok och som returnerar det instansierade objektet. Detta signaleras genom att en absolut importsökväg till fabriken görs tillgänglig under den speciella nyckeln '()'
. Här är ett konkret exempel:
formatterare:
kort:
format: '%(message)s'
standard:
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
svar: 42
YAML-utdraget ovan definierar tre formaterare. Den första, med id brief
, är en standard logging.Formatter
-instans med den angivna formatsträngen. Den andra, med id default
, har ett längre format och definierar även tidsformatet explicit, och kommer att resultera i en logging.Formatter
som initieras med dessa två formatsträngar. Visas i Python-källform, brief
och default
formatterarna har konfigurationsunderordnade ordböcker:
{
'format' : '%(message)s'
}
och:
{
'format' : '%(asctime)s %(levelname)-8s %(name)-15s %(message)s',
'datefmt' : '%Y-%m-%d %H:%M:%S'
}
respektive, och eftersom dessa ordböcker inte innehåller specialnyckeln '()'
, härleds instansen från sammanhanget: som ett resultat skapas standard logging.Formatter
-instanser. Konfigurationsunderordlistan för den tredje formatteraren, med id custom
, är:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'svar' : 42
}
och denna innehåller specialnyckeln '()'
, vilket innebär att en användardefinierad instansiering önskas. I detta fall kommer den angivna fabriksinställningen att användas. Om det är en faktisk callable kommer den att användas direkt - i annat fall, om du anger en sträng (som i exemplet) kommer den faktiska callable att lokaliseras med hjälp av normala importmekanismer. Den anropbara funktionen anropas med de återstående objekten i konfigurationsunderordlistan som nyckelordsargument. I exemplet ovan kommer formatteraren med id custom
att antas returneras av anropet:
my.package.customFormatterFactory(bar='baz', spam=99.9, answer=42)
Varning
Värdena för nycklar som bar
, spam
och answer
i exemplet ovan bör inte vara konfigurationsordböcker eller referenser som cfg://foo
eller ext://bar
, eftersom de inte kommer att bearbetas av konfigurationsmaskineriet, utan skickas till den anropsbara som de är.
Nyckeln '()'
har använts som specialnyckel eftersom den inte är ett giltigt nyckelordsparameternamn och därför inte krockar med namnen på de nyckelordsargument som används i anropet. '()'
fungerar också som en mnemonik för att motsvarande värde är en callable.
Ändrad i version 3.11: Medlemmen filters
i handlers
och loggers
kan ta filterinstanser utöver id:n.
Du kan också ange en specialnyckel '.'
vars värde är en mappning av attributnamn till värden. Om den hittas kommer de angivna attributen att ställas in på det användardefinierade objektet innan det returneras. Således, med följande konfiguration:
{
'()' : 'my.package.customFormatterFactory',
'bar' : 'baz',
'spam' : 99.9,
'answer' : 42,
'.' {
'foo': 'bar',
'baz': 'bozz'
}
}
kommer den returnerade formateraren att ha attributet foo
satt till 'bar'
och attributet baz
satt till 'bozz'
.
Varning
Värdena för attribut som foo
och baz
i exemplet ovan bör inte vara konfigurationsordböcker eller referenser som cfg://foo
eller ext://bar
, eftersom de inte kommer att bearbetas av konfigurationsmaskineriet, utan anges som attributvärden som de är.
Konfigurationsordning för handläggare¶
Hanterare konfigureras i alfabetisk ordning efter sina nycklar, och en konfigurerad hanterare ersätter konfigurationsordlistan i (en arbetskopia av) ordlistan handlers
i schemat. Om du använder en konstruktion som cfg://handlers.foo
, pekar handlers['foo']
först på konfigurationsordlistan för hanteraren med namnet foo
, och senare (när den hanteraren har konfigurerats) pekar den på den konfigurerade hanterarinstansen. Således kan cfg://handlers.foo
peka på antingen en ordbok eller en hanterarinstans. I allmänhet är det klokt att namnge hanterare på ett sådant sätt att beroende hanterare konfigureras efter alla hanterare som de är beroende av. Det gör att något som cfg://handlers.foo
kan användas för att konfigurera en hanterare som är beroende av hanteraren foo
. Om den beroende hanteraren hette bar
skulle det uppstå problem, eftersom konfigurationen av bar
skulle försöka göras före konfigurationen av foo
, och foo
skulle ännu inte ha konfigurerats. Om den beroende hanteraren däremot hette foobar
skulle den konfigureras efter foo
, vilket skulle leda till att cfg://handlers.foo
skulle lösa upp till den konfigurerade hanteraren foo
, och inte till dess konfigurationsordbok.
Tillgång till externa objekt¶
Det finns tillfällen då en konfiguration behöver hänvisa till objekt utanför konfigurationen, till exempel sys.stderr
. Om konfigurationsdikten är konstruerad med Python-kod är detta enkelt, men ett problem uppstår när konfigurationen tillhandahålls via en textfil (t.ex. JSON, YAML). I en textfil finns det inget standardiserat sätt att skilja sys.stderr
från den bokstavliga strängen 'sys.stderr
. För att underlätta denna distinktion letar konfigurationssystemet efter vissa speciella prefix i strängvärden och behandlar dem på ett speciellt sätt. Om till exempel den bokstavliga strängen 'ext://sys.stderr'
anges som ett värde i konfigurationen, kommer ext://
att tas bort och resten av värdet behandlas med normala importmekanismer.
Hanteringen av sådana prefix sker på ett sätt som är analogt med protokollhantering: det finns en generisk mekanism för att leta efter prefix som matchar det reguljära uttrycket ^(?P<prefix>[a-z]+)://(?P<suffix>.*)$
varvid, om prefixet
känns igen, uffixet
bearbetas på ett prefixberoende sätt och resultatet av bearbetningen ersätter strängvärdet. Om prefixet inte känns igen kommer strängvärdet att lämnas som det är.
Tillgång till interna objekt¶
Förutom externa objekt finns det ibland också behov av att hänvisa till objekt i konfigurationen. Detta görs implicit av konfigurationssystemet för saker som det känner till. Till exempel konverteras strängvärdet 'DEBUG
för en nivå
i en logger eller hanterare automatiskt till värdet logging.DEBUG
, och posterna handlers
, filters
och formatter
tar ett objekt-ID och löser upp till lämpligt destinationsobjekt.
Det behövs dock en mer generisk mekanism för användardefinierade objekt som inte är kända av modulen logging
. Tänk till exempel på logging.handlers.MemoryHandler
, som tar ett target
-argument som är en annan hanterare att delegera till. Eftersom systemet redan känner till den här klassen behöver det angivna target
i konfigurationen bara vara objekt-id för den relevanta målhanteraren, och systemet kommer att lösa upp till hanteraren från id. Om en användare däremot definierar en my.package.MyHandler
som har en alternativ
hanterare, skulle konfigurationssystemet inte veta att alternativ
refererar till en hanterare. För att tillgodose detta tillåter ett generiskt upplösningssystem användaren att ange:
handlers:
file:
# configuration of file handler goes here
custom:
(): my.package.MyHandler
alternate: cfg://handlers.file
Den bokstavliga strängen 'cfg://handlers.file'
kommer att lösas på ett analogt sätt som strängar med prefixet ext://
, men letar i själva konfigurationen snarare än i importnamnrymden. Mekanismen tillåter åtkomst via punkt eller index, på ett liknande sätt som det som tillhandahålls av str.format
. Således, givet följande utdrag:
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.
i konfigurationen, skulle strängen 'cfg://handlers
lösas upp mot diktatet med nyckeln handlers
, strängen 'cfg://handlers.email
skulle lösas upp mot diktatet med nyckeln email
i diktatet handlers
, och så vidare. Strängen 'cfg://handlers.email.toaddrs[1]
skulle upplösas till 'dev_team@domain.tld'
och strängen 'cfg://handlers.email.toaddrs[0]'
skulle upplösas till värdet 'support_team@domain.tld'
. Värdet subject
kan nås med antingen 'cfg://handlers.email.subject'
eller, på motsvarande sätt, 'cfg://handlers.email[subject]'
. Den senare formen behöver endast användas om nyckeln innehåller mellanslag eller icke-alfanumeriska tecken. Observera att tecknen [
och ]
inte är tillåtna i nycklarna. Om ett indexvärde endast består av decimala siffror kommer åtkomstförsök att göras med hjälp av motsvarande heltalsvärde, med återgång till strängvärdet vid behov.
Med en sträng cfg://handlers.myhandler.mykey.123
kommer detta att lösas upp till config_dict['handlers']['myhandler']['mykey']['123']
. Om strängen anges som cfg://handlers.myhandler.mykey[123]
kommer systemet att försöka hämta värdet från config_dict['handlers']['myhandler']['mykey'][123]
, och återgå till config_dict['handlers']['myhandler']['mykey']['123']
om det misslyckas.
Importupplösning och anpassade importörer¶
Importresolution använder som standard den inbyggda funktionen __import__()
för att göra sin import. Du kanske vill ersätta detta med din egen importmekanism: i så fall kan du ersätta attributet importer
i DictConfigurator
eller dess superklass, BaseConfigurator
. Du måste dock vara försiktig på grund av hur funktioner nås från klasser via deskriptorer. Om du använder en Python callable för att göra din import, och du vill definiera den på klassnivå snarare än instansnivå, måste du linda in den med staticmethod()
. Till exempel:
from importlib import import_module
from logging.config import BaseConfigurator
BaseConfigurator.importer = staticmethod(import_module)
Du behöver inte omsluta med staticmethod()
om du ställer in importkallelsen på en konfigurator instans.
Konfigurera QueueHandler och QueueListener¶
Om du vill konfigurera en QueueHandler
, och observera att denna normalt används tillsammans med en QueueListener
, kan du konfigurera båda tillsammans. Efter konfigurationen kommer QueueListener
-instansen att vara tillgänglig som attributet listener`
för den skapade hanteraren, och den kommer i sin tur att vara tillgänglig för dig genom att använda getHandlerByName()
och skicka det namn du har använt för QueueHandler
i din konfiguration. Ordboksschemat för konfigurering av paret visas i YAML-exemplet nedan.
handlers:
qhand:
class: logging.handlers.QueueHandler
queue: my.module.queue_factory
listener: my.package.CustomListener
handlers:
- hand_name_1
- hand_name_2
...
Nycklarna queue
och listener
är valfria.
Om nyckeln queue
finns, kan motsvarande värde vara något av följande:
Ett objekt som implementerar de publika API:erna
Queue.put_nowait
ochQueue.get
. Det kan t.ex. vara en faktisk instans avqueue.Queue
eller en underklass av denna, eller en proxy som erhålls avmultiprocessing.managers.SyncManager.Queue()
.Detta är naturligtvis bara möjligt om du konstruerar eller ändrar konfigurationsordlistan i kod.
En sträng som löser upp till en anropsbar som, när den anropas utan argument, returnerar den köinstans som ska användas. Denna anropsbarhet kan vara en
queue.Queue
-underklass eller en funktion som returnerar en lämplig köinstans, till exempelmy.module.queue_factory()
.En dict med en
'()'
nyckel som är konstruerad på vanligt sätt som beskrivs i Användardefinierade objekt. Resultatet av denna konstruktion bör vara en instans avqueue.Queue
.
Om nyckeln queue
saknas skapas och används en standardiserad obegränsad queue.Queue
-instans.
Om nyckeln listener
finns, kan motsvarande värde vara något av följande:
En underklass till
logging.handlers.QueueListener
. Detta är naturligtvis bara möjligt om du konstruerar eller ändrar konfigurationsordlistan i kod.En sträng som motsvarar en klass som är en underklass till
QueueListener
, t.ex.'my.package.CustomListener'
.En dict med en
'()'
nyckel som är konstruerad på det vanliga sättet som diskuteras i Användardefinierade objekt. Resultatet av denna konstruktion bör vara en callable med samma signatur som initialiseraren förQueueListener
.
Om nyckeln listener
saknas används logging.handlers.QueueListener
.
Värdena under nyckeln handlers
är namnen på andra handlers i konfigurationen (visas inte i utdraget ovan) som kommer att skickas till kölyssnaren.
Alla anpassade köhanterings- och lyssnarklasser måste definieras med samma initialiseringssignaturer som QueueHandler
och QueueListener
.
Tillagd i version 3.12.
Format för konfigurationsfil¶
Konfigurationsfilens format som förstås av fileConfig()
är baserat på configparser
funktionalitet. Filen måste innehålla avsnitt kallade [loggers]
, [handlers]
och [formatters]
som identifierar de entiteter av varje typ som definieras i filen. För varje sådan entitet finns ett separat avsnitt som anger hur den entiteten konfigureras. För en logger med namnet log01
i avsnittet [loggers]
finns alltså relevanta konfigurationsdetaljer i avsnittet [logger_log01]
. På samma sätt kommer en hanterare som heter hand01
i avsnittet [handlers]
att ha sin konfiguration i ett avsnitt som heter [handler_hand01]
, medan en formaterare som heter form01
i avsnittet [formaterare]
kommer att ha sin konfiguration angiven i ett avsnitt som heter [formaterare_form01]
. Konfigurationen för rotloggaren måste anges i ett avsnitt som heter [logger_root]
.
Anteckning
API:et fileConfig()
är äldre än API:et dictConfig()
och innehåller inte funktioner som täcker vissa aspekter av loggning. Du kan t.ex. inte konfigurera Filter
-objekt, som möjliggör filtrering av meddelanden utöver enkla heltalsnivåer, med hjälp av fileConfig()
. Om du behöver ha instanser av Filter
i din loggningskonfiguration måste du använda dictConfig()
. Observera att framtida förbättringar av konfigurationsfunktionaliteten kommer att läggas till i dictConfig()
, så det är värt att överväga att övergå till detta nyare API när det är lämpligt att göra det.
Exempel på dessa avsnitt i filen ges nedan.
[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
Rotloggaren måste ange en nivå och en lista över hanterare. Ett exempel på ett root logger-avsnitt ges nedan.
[logger_root]
level=NOTSET
handlers=hand01
Inmatningen level
kan vara DEBUG, INFO, WARNING, ERROR, CRITICAL
eller NOTSET
. Endast för rotloggaren betyder NOTSET
att alla meddelanden loggas. Nivåvärdena utvärderas i sammanhanget för paketets logging
-namnrymd.
Posten handlers
är en kommaseparerad lista med namn på hanterare som måste finnas i avsnittet [handlers]
. Dessa namn måste finnas i avsnittet [handlers]
och ha motsvarande avsnitt i konfigurationsfilen.
För andra loggrar än rotloggaren krävs viss ytterligare information. Detta illustreras av följande exempel.
[logger_parser]
level=DEBUG
handlers=hand01
propagate=1
qualname=compiler.parser
Posterna level
och handlers
tolkas som för rotloggaren, förutom att om nivån för en logger som inte är rotloggare anges som NOTSET
, konsulterar systemet loggar högre upp i hierarkin för att fastställa loggarens faktiska nivå. Posten propagate
är satt till 1 för att ange att meddelanden måste spridas till handläggare högre upp i loggerhierarkin från denna logger, eller 0 för att ange att meddelanden inte sprids till handläggare högre upp i hierarkin. Posten qualname
är loggarens hierarkiska kanalnamn, det vill säga det namn som används av programmet för att hämta loggern.
Avsnitt som specificerar konfigurationen av handläggaren exemplifieras av följande.
[handler_hand01]
class=StreamHandler
level=NOTSET
formatter=form01
args=(sys.stdout,)
Objektet class
anger hanterarens klass (som bestäms av eval()
i logging
-paketets namnrymd). level
tolkas som för loggare och NOTSET
tolkas som ”logga allt”.
Posten formatter
anger nyckelnamnet på formateraren för denna hanterare. Om den är tom används en standardformattering (logging._defaultFormatter
). Om ett namn anges måste det finnas i avsnittet [formatters]
och ha ett motsvarande avsnitt i konfigurationsfilen.
När evaluated i kontexten för paketet logging
, är posten args
en lista över argument till konstruktorn för hanterarklassen. Se konstruktorerna för relevanta hanterare eller exemplen nedan för att se hur typiska poster konstrueras. Om det inte anges är standardvärdet ()
.
Den valfria posten kwargs
, när utvärderad i sammanhanget för paketet logging
, är nyckelordsargumentet dict till konstruktorn för hanterarklassen. Om det inte anges är standardvärdet {}
.
[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}
Avsnitt som anger formatteringskonfiguration kännetecknas av följande.
[formatter_form01]
format=F1 %(asctime)s %(levelname)s %(message)s %(customfield)s
datefmt=
style=%
validate=True
defaults={'customfield': 'defaultvalue'}
class=logging.Formatter
Argumenten för formatteringskonfigurationen är desamma som nycklarna i ordboksschemat formatters section.
Posten defaults
, när den utvärderas i sammanhanget för paketet logging
, är en ordlista med standardvärden för anpassade formateringsfält. Om den inte anges är standardvärdet None
.
Anteckning
På grund av användningen av eval()
enligt beskrivningen ovan finns det potentiella säkerhetsrisker som uppstår när listen()
används för att skicka och ta emot konfigurationer via sockets. Riskerna är begränsade till när flera användare utan ömsesidigt förtroende kör kod på samma maskin; se dokumentationen för listen()
för mer information.
Se även
- Modul
logging
API-referens för loggningsmodulen.
- Modul
logging.handlers
Användbara hanterare som ingår i loggningsmodulen.