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 eller ImportError 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 metod configure(). Modulen logging.config har ett anropbart attribut dictConfigClass som initialt är inställt på DictConfigurator. Du kan ersätta värdet på dictConfigClass med en egen lämplig implementation.

dictConfig() anropar dictConfigClass som skickar den angivna ordlistan, och anropar sedan configure()-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 anropa DictConfigurator.__init__() i sin egen __init__(), och sedan ställa in anpassade prefix som skulle kunna användas i det efterföljande configure()-anropet. dictConfigClass skulle bindas till denna nya underklass, och sedan skulle dictConfig() 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 och RuntimeError om filen är ogiltig eller tom.

Parametrar:
  • fname – Ett filnamn, eller ett filliknande objekt, eller en instans härledd från RawConfigParser. Om en RawConfigParser-deriverad instans skickas, används den som den är. Annars instansieras en ConfigParser och konfigurationen läses av den från objektet som passeras i fname. Om det har en readline()-metod, antas det vara ett filliknande objekt och läses med read_file(); annars antas det vara ett filnamn och skickas till read().

  • 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ör fname. 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 av dictConfig() eller fileConfig(). Returnerar en Thread-instans på vilken du kan anropa start() för att starta servern, och som du kan join() när det är lämpligt. För att stoppa servern, anropa stopListening().

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 anropsbarnet verify kan utföra signaturverifiering och/eller dekryptering. Anropsbarheten verify anropas med ett enda argument - de byte som mottagits över sockeln - och bör returnera de byte som skall behandlas, eller None 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 anropar listen(). Om processen som anropar listen() 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ändarens listen()-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 argumentet verify till listen() 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 ange disable_existing_loggers som False i den konfiguration du skickar.

logging.config.stopListening()

Stoppar den lyssnande server som skapades med ett anrop till listen(). Detta anropas vanligtvis innan join() anropas på returvärdet från listen().

Ö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ör Formatter, så den här nyckeln är mest användbar för instansiering av en anpassad underklass till Formatter. 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 en logging.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 en logging.StreamHandler, med sys.stdout som underliggande ström. Hanteraren med id file instansieras som en logging.handlers.RotatingFileHandler` med nyckelordsargumenten filnamn='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:et fileConfig().

    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ärdet True. Detta värde ignoreras om incremental är True.

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 och Queue.get. Det kan t.ex. vara en faktisk instans av queue.Queue eller en underklass av denna, eller en proxy som erhålls av multiprocessing.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 exempel my.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 av queue.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ör QueueListener.

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.