warnings
— Varningskontroll¶
Källkod: Lib/warnings.py
Varningsmeddelanden utfärdas vanligtvis i situationer där det är lämpligt att varna användaren för ett visst tillstånd i ett program, där detta tillstånd (normalt) inte motiverar att ett undantag görs och programmet avslutas. Man kan t.ex. vilja utfärda en varning när ett program använder en föråldrad modul.
Python-programmerare utfärdar varningar genom att anropa funktionen warn()
som definieras i denna modul. (C-programmerare använder PyErr_WarnEx()
; se Hantering av undantag för detaljer).
Varningsmeddelanden skrivs normalt till sys.stderr
, men deras disposition kan ändras på ett flexibelt sätt, från att ignorera alla varningar till att omvandla dem till undantag. Dispositionen för varningar kan variera beroende på varningskategorin, texten i varningsmeddelandet och källplatsen där den utfärdades. Upprepningar av en viss varning för samma källplats undertrycks vanligtvis.
Det finns två steg i varningskontrollen: först, varje gång en varning utfärdas, avgörs om ett meddelande ska utfärdas eller inte; därefter, om ett meddelande ska utfärdas, formateras och skrivs det ut med hjälp av en hook som kan ställas in av användaren.
Avgörandet om ett varningsmeddelande ska utfärdas styrs av varningsfiltret, som är en sekvens av matchande regler och åtgärder. Regler kan läggas till i filtret genom att anropa filterwarnings()
och återställas till dess standardtillstånd genom att anropa resetwarnings()
.
Utskriften av varningsmeddelanden sker genom anrop av showwarning()
, som kan åsidosättas; standardimplementeringen av denna funktion formaterar meddelandet genom anrop av formatwarning()
, som också kan användas av anpassade implementeringar.
Se även
logging.captureWarnings()
gör att du kan hantera alla varningar med standardinfrastrukturen för loggning.
Varningskategorier¶
Det finns ett antal inbyggda undantag som representerar varningskategorier. Denna kategorisering är användbar för att kunna filtrera bort grupper av varningar.
Även om dessa tekniskt sett är inbyggda undantag, dokumenteras de här, eftersom de konceptuellt sett hör till varningsmekanismen.
Användarkod kan definiera ytterligare varningskategorier genom att subklassa en av standardvarningskategorierna. En varningskategori måste alltid vara en subklass av klassen Warning
.
Följande klasser av varningskategorier är för närvarande definierade:
Klass |
Beskrivning |
---|---|
Detta är basklassen för alla klasser i varningskategorin. Den är en underklass till |
|
Standardkategorin för |
|
Baskategori för varningar om föråldrade funktioner när dessa varningar är avsedda för andra Python-utvecklare (ignoreras som standard, såvida de inte utlöses av kod i |
|
Baskategori för varningar om tvivelaktiga syntaktiska egenskaper. |
|
Baskategori för varningar om tvivelaktiga runtime-funktioner. |
|
Baskategori för varningar om föråldrade funktioner när dessa varningar är avsedda för slutanvändare av program som är skrivna i Python. |
|
Baskategori för varningar om funktioner som kommer att bli föråldrade i framtiden (ignoreras som standard). |
|
Baskategori för varningar som utlöses under import av en modul (ignoreras som standard). |
|
Baskategori för varningar relaterade till Unicode. |
|
Baskategori för varningar relaterade till |
|
Baskategori för varningar relaterade till resursanvändning (ignoreras som standard). |
Ändrad i version 3.7: Tidigare skilde sig DeprecationWarning
och FutureWarning
åt baserat på om en funktion togs bort helt eller ändrade sitt beteende. De skiljer sig nu åt baserat på deras avsedda målgrupp och hur de hanteras av standardfiltren för varningar.
Filtret för varningar¶
Filtret för varningar styr om varningar ska ignoreras, visas eller omvandlas till fel (skapa ett undantag).
Begreppsmässigt upprätthåller varningsfiltret en ordnad lista med filterspecifikationer; en specifik varning matchas mot varje filterspecifikation i listan i tur och ordning tills en matchning hittas; filtret avgör hur matchningen ska hanteras. Varje post är en tupel av formen (action, message, category, module, lineno), där:
action är en av följande strängar:
Värde
Disposition
"standard"
skriva ut den första förekomsten av matchande varningar för varje plats (modul + radnummer) där varningen utfärdas
"fel"
omvandla matchande varningar till undantag
"ignorera"
skriv aldrig ut matchande varningar
"alltid"
alltid skriva ut matchande varningar
"alla"
alias till ”alltid”
"modul"
skriva ut den första förekomsten av matchande varningar för varje modul där varningen utfärdas (oavsett radnummer)
”en gång”
skriv bara ut den första förekomsten av matchande varningar, oavsett plats
message är en sträng som innehåller ett reguljärt uttryck som början av varningsmeddelandet måste matcha, utan hänsyn till skiftlägesskillnader. I
-W
ochPYTHONWARNINGS
är message en bokstavlig sträng som början av varningsmeddelandet måste innehålla (utan hänsyn till skiftlägesskillnader), varvid eventuella blanksteg i början eller slutet av message ignoreras.category är en klass (en subklass av
Warning
) som varningskategorin måste vara en subklass av för att matcha.module är en sträng som innehåller ett reguljärt uttryck som början av det fullständigt kvalificerade modulnamnet måste matcha (skiftlägeskänsligt). I
-W
ochPYTHONWARNINGS
är module en bokstavlig sträng som det fullständigt kvalificerade modulnamnet måste vara lika med (skiftlägeskänsligt), utan hänsyn till eventuella blanksteg i början eller slutet av module.lineno är ett heltal som det radnummer där varningen inträffade måste matcha, eller
0
för att matcha alla radnummer.
Eftersom klassen Warning
är härledd från den inbyggda klassen Exception
kan vi helt enkelt höja category(message)
för att omvandla en varning till ett fel.
Om en varning rapporteras och inte matchar något registrerat filter tillämpas ”standard”-åtgärden (därav namnet).
Kriterier för undertryckande av upprepad varning¶
De filter som undertrycker upprepade varningar tillämpar följande kriterier för att avgöra om en varning anses vara upprepad:
"standard"
: En varning betraktas som en upprepning endast om (message, category, module, lineno) är identiska."modul"
: En varning betraktas som en upprepning om (message, category, module) är desamma, utan hänsyn till radnummer."en gång"
: En varning betraktas som en upprepning om (meddelande, kategori) är desamma, utan hänsyn till modul- och radnummer.
Beskrivning av varningsfilter¶
Varningsfiltret initieras av -W
alternativ som skickas till Python-tolkens kommandorad och miljövariabeln PYTHONWARNINGS
. Tolken sparar argumenten för alla medföljande poster utan tolkning i sys.warnoptions
; modulen warnings
analyserar dessa när den importeras första gången (ogiltiga alternativ ignoreras efter att ett meddelande skrivits ut till sys.stderr
).
Enskilda varningsfilter anges som en sekvens av fält åtskilda med kolon:
åtgärd:meddelande:kategori:modul:linje
Betydelsen av vart och ett av dessa fält beskrivs i Filtret för varningar. När flera filter listas på en rad (som för PYTHONWARNINGS
) separeras de enskilda filtren med kommatecken och de filter som listas senare har företräde framför de som listas före dem (eftersom de tillämpas från vänster till höger och de senast tillämpade filtren har företräde framför de tidigare).
Vanligt förekommande varningsfilter gäller antingen alla varningar, varningar i en viss kategori eller varningar som orsakas av vissa moduler eller paket. Några exempel:
default # Visa alla varningar (även de som ignoreras som standard)
ignore # Ignorera alla varningar
error # Konvertera alla varningar till fel
error::ResourceWarning # Behandla ResourceWarning-meddelanden som fel
default::DeprecationWarning # Visa DeprecationWarning-meddelanden
ignore,default:::mymodule # Rapportera bara varningar som utlöses av "mymodule"
error:::mymodule # Konvertera varningar till fel i "mymodule"
Standard varningsfilter¶
Som standard installerar Python flera varningsfilter som kan åsidosättas med kommandoradsalternativet -W
, miljövariabeln PYTHONWARNINGS
och anrop till filterwarnings()
.
I vanliga versionsversioner har standardvarningsfiltret följande poster (i prioritetsordning):
default::DeprecationWarning:__main__
ignorera::DeprecationWarning
ignore::PendingDeprecationWarning
ignore::ImportWarning
ignore::ResourceWarning
I en debug build är listan över standardvarningsfilter tom.
Ändrad i version 3.2: DeprecationWarning
ignoreras nu som standard i tillägg till PendingDeprecationWarning
.
Ändrad i version 3.7: DeprecationWarning
visas återigen som standard när den utlöses direkt av kod i __main__
.
Ändrad i version 3.7: BytesWarning
visas inte längre i standardfilterlistan och konfigureras istället via sys.warnoptions
när -b
anges två gånger.
Åsidosätta standardfiltret¶
Utvecklare av applikationer skrivna i Python kanske vill dölja alla varningar på Python-nivå från sina användare som standard, och bara visa dem när de kör tester eller på annat sätt arbetar med applikationen. Attributet sys.warnoptions
som används för att skicka filterkonfigurationer till tolken kan användas som en markör för att ange om varningar ska inaktiveras eller inte:
import sys
if not sys.warnoptions:
import warnings
warnings.simplefilter("ignore")
Utvecklare av testlöpare för Python-kod rekommenderas att istället se till att alla varningar visas som standard för den kod som testas, med hjälp av kod som:
import sys
if not sys.warnoptions:
import os, warnings
warnings.simplefilter("default") # Change the filter in this process
os.environ["PYTHONWARNINGS"] = "default" # Also affect subprocesses
Slutligen rekommenderas utvecklare av interaktiva skal som kör användarkod i ett annat namnrymd än __main__
att se till att DeprecationWarning
-meddelanden görs synliga som standard, med hjälp av kod som följande (där user_ns
är den modul som används för att köra kod som matas in interaktivt):
import warnings
warnings.filterwarnings("default", category=DeprecationWarning,
module=user_ns.get("__name__"))
Tillfälligt undertryckande av varningar¶
Om du använder kod som du vet kommer att ge upphov till en varning, t.ex. en föråldrad funktion, men inte vill se varningen (även när varningar uttryckligen har konfigurerats via kommandoraden), är det möjligt att undertrycka varningen med hjälp av kontexthanteraren catch_warnings
:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
fxn()
När du befinner dig i kontexthanteraren ignoreras alla varningar helt enkelt. Detta gör att du kan använda känd föråldrad kod utan att behöva se varningen samtidigt som varningen inte undertrycks för annan kod som kanske inte är medveten om att den använder föråldrad kod.
Anteckning
Se Samtidig säkerhet för kontexthanterare för detaljer om samtidighetssäkerheten för kontexthanteraren
catch_warnings
när den används i program som använder flera trådar eller asynkrona funktioner.
Varningar för testning¶
Om du vill testa varningar som orsakas av kod använder du kontexthanteraren catch_warnings
. Med den kan du tillfälligt ändra varningsfiltret för att underlätta din testning. Gör till exempel följande för att fånga upp alla varningar för att kontrollera:
import warnings
def fxn():
warnings.warn("deprecated", DeprecationWarning)
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Trigger a warning.
fxn()
# Verify some things
assert len(w) == 1
assert issubclass(w[-1].category, DeprecationWarning)
assert "deprecated" in str(w[-1].message)
Man kan också få alla varningar att bli undantag genom att använda error
istället för always
. En sak man bör vara medveten om är att om en varning redan har tagits upp på grund av en once
/default
-regel, så kommer varningen inte att visas igen oavsett vilka filter som ställs in, såvida inte varningsregistret som är relaterat till varningen har rensats.
När kontexthanteraren avslutas återställs varningsfiltret till det tillstånd som rådde när kontexten skapades. Detta förhindrar att testerna ändrar varningsfiltret på oväntade sätt mellan testerna, vilket leder till obestämda testresultat.
Anteckning
Se Samtidig säkerhet för kontexthanterare för detaljer om samtidighetssäkerheten för kontexthanteraren
catch_warnings
när den används i program som använder flera trådar eller asynkrona funktioner.
När du testar flera operationer som ger upphov till samma typ av varning är det viktigt att du testar dem på ett sätt som bekräftar att varje operation ger upphov till en ny varning (t.ex. genom att ställa in att varningar ska ges upphov till undantag och kontrollera att operationerna ger upphov till undantag, kontrollera att varningslistans längd fortsätter att öka efter varje operation, eller radera de tidigare posterna från varningslistan före varje ny operation).
Uppdatering av kod för nya versioner av beroenden¶
Varningskategorier som främst är av intresse för Python-utvecklare (snarare än slutanvändare av program som skrivits i Python) ignoreras som standard.
Noterbart är att denna ”ignoreras som standard”-lista innehåller DeprecationWarning
(för alla moduler utom __main__
), vilket innebär att utvecklare bör se till att testa sin kod med typiskt ignorerade varningar synliggjorda för att i god tid få meddelanden om framtida API-ändringar (oavsett om det är i standardbiblioteket eller tredjepartspaket).
I det ideala fallet har koden en lämplig testsvit och testköraren tar hand om att implicit aktivera alla varningar när tester körs (testköraren som tillhandahålls av modulen unittest
gör detta).
I mindre idealiska fall kan applikationer kontrolleras för användning av föråldrade gränssnitt genom att skicka -Wd
till Python-tolken (detta är en förkortning för -W default
) eller ställa in PYTHONWARNINGS=default
i miljön. Detta aktiverar standardhantering för alla varningar, inklusive de som ignoreras som standard. För att ändra vilken åtgärd som vidtas för varningar kan du ändra vilket argument som skickas till -W
(t.ex. -W error
). Se flaggan -W
för mer information om vad som är möjligt.
Tillgängliga funktioner¶
- warnings.warn(message, category=None, stacklevel=1, source=None, *, skip_file_prefixes=())¶
Utfärda en varning, eller kanske ignorera den eller höja en undantag. Argumentet category, om det anges, måste vara en varning kategori klass; standardvärdet är
UserWarning
. Alternativt kan message vara enWarning
-instans, i vilket fall category ignoreras ochmessage.__class__
används. I detta fall blir meddelandetextenstr(message)
. Denna funktion genererar ett undantag om den specifika varningen ändras till ett fel av warnings filter. Argumentet stacklevel kan användas av wrapper-funktioner skrivna i Python, så här:def deprecated_api(meddelande): warnings.warn(message, DeprecationWarning, stacklevel=2)
Detta gör att varningen hänvisar till
deprecated_api
’s anropare, snarare än till källan tilldeprecated_api
själv (eftersom det senare skulle motverka syftet med varningsmeddelandet).Nyckelordsargumentet skip_file_prefixes kan användas för att ange vilka stackramar som ska ignoreras när man räknar stacknivåer. Detta kan vara användbart när du vill att varningen alltid ska visas på anropsplatser utanför ett paket när en konstant stacklevel inte passar alla anropsvägar eller på annat sätt är svår att underhålla. Om det anges måste det vara en tupel av strängar. När prefix anges åsidosätts stacklevel implicit till att vara
max(2, stacklevel)
. För att få en varning att tillskrivas den som anropar från utanför det aktuella paketet kan du skriva:# example/lower.py _warn_skips = (os.path.dirname(__file__),) def one_way(r_luxury_yacht=None, t_wobbler_mangrove=None): if r_luxury_yacht: warnings.warn("Please migrate to t_wobbler_mangrove=.", skip_file_prefixes=_warn_skips) # example/higher.py from . import lower def another_way(**kw): lower.one_way(**kw)
Detta gör att varningen hänvisar till både anropsställena
example.lower.one_way()
ochpackage.higher.another_way()
endast vid anrop av kod som ligger utanförexample
-paketet.source, om det anges, är det förstörda objekt som gav upphov till en
ResourceWarning
.Ändrad i version 3.6: Parametern source har lagts till.
Ändrad i version 3.12: Lagt till skip_file_prefixes.
- warnings.warn_explicit(message, category, filename, lineno, module=None, registry=None, module_globals=None, source=None)¶
Detta är ett lågnivågränssnitt till funktionaliteten i
warn()
, som explicit skickar in meddelandet, kategorin, filnamnet och radnumret, samt eventuellt modulnamnet och registret (som bör vara modulens__warningregistry__
-ordbok). Modulnamnet är som standard filnamnet med.py
borttaget; om inget register skickas med undertrycks aldrig varningen. message måste vara en sträng och category en underklass tillWarning
eller så kan message vara en instans avWarning
, i vilket fall category ignoreras.module_globals, om det anges, bör vara det globala namnrymden som används av koden för vilken varningen utfärdas. (Detta argument används för att visa källan för moduler som finns i zip-filer eller andra importkällor som inte är filsystem).
source, om det anges, är det förstörda objekt som gav upphov till en
ResourceWarning
.Ändrad i version 3.6: Lägg till parametern source.
- warnings.showwarning(message, category, filename, lineno, file=None, line=None)¶
Skriva en varning till en fil. Standardimplementeringen anropar
formatwarning(message, category, filename, lineno, line)
och skriver den resulterande strängen till file, som är standard försys.stderr
. Du kan ersätta denna funktion med en valfri anropsbar funktion genom att tilldela den tillwarnings.showwarning
. line är en rad källkod som ska ingå i varningsmeddelandet; om line inte anges kommershowwarning()
att försöka läsa den rad som anges av filename och lineno.
- warnings.formatwarning(message, category, filename, lineno, line=None)¶
Formatera en varning på vanligt sätt. Detta returnerar en sträng som kan innehålla inbäddade nya rader och som slutar med en ny rad. line är en rad med källkod som ska ingå i varningsmeddelandet; om line inte anges kommer
formatwarning()
att försöka läsa den rad som anges av filename och lineno.
- warnings.filterwarnings(action, message='', category=Warning, module='', lineno=0, append=False)¶
Infoga en post i listan över warnings filter specifications. Som standard infogas posten längst fram; om append är true infogas den i slutet. Detta kontrollerar argumentens typer, sammanställer de reguljära uttrycken message och module och infogar dem som en tupel i listan över varningsfilter. Poster längre fram i listan åsidosätter poster längre fram i listan, om båda matchar en viss varning. Utelämnade argument får som standard ett värde som matchar allt.
- warnings.simplefilter(action, category=Warning, lineno=0, append=False)¶
Infoga en enkel post i listan över warnings filter specifications. Betydelsen av funktionsparametrarna är densamma som för
filterwarnings()
, men reguljära uttryck behövs inte eftersom det infogade filtret alltid matchar alla meddelanden i alla moduler så länge som kategorin och radnumret matchar.
- warnings.resetwarnings()¶
Återställer filtret för varningar. Detta tar bort effekten av alla tidigare anrop till
filterwarnings()
, inklusive effekten av kommandoradsalternativen-W
och anrop tillsimplefilter()
.
- @warnings.deprecated(msg, *, category=DeprecationWarning, stacklevel=1)¶
Dekorator för att ange att en klass, funktion eller överbelastning är avskriven.
När denna dekorator används på ett objekt kan varningar om att objektet är föråldrat utfärdas vid körning när objektet används. static type checkers kommer också att generera en diagnos vid användning av det föråldrade objektet.
Användning:
from warnings import deprecated from typing import overload @deprecated("Use B instead") class A: pass @deprecated("Use g instead") def f(): pass @overload @deprecated("int support is deprecated") def g(x: int) -> int: ... @overload def g(x: str) -> int: ...
Den varning som specificeras av category kommer att utfärdas vid körning vid användning av föråldrade objekt. För funktioner sker detta vid anrop, för klasser vid instansiering och skapande av underklasser. Om category är
None
avges ingen varning vid körning. stacklevel avgör var varningen utfärdas. Om den är1
(standard) skickas varningen till den som direkt anropar det föråldrade objektet; om den är högre skickas den längre upp i stacken. Den statiska typkontrollens beteende påverkas inte av argumenten category och stacklevel.Deprecation-meddelandet som skickas till dekoratorn sparas i attributet
__deprecated__
på det dekorerade objektet. Om det tillämpas på en överbelastning måste dekoratorn vara efter dekoratorn@overload
för att attributet ska finnas på överbelastningen som returneras avtyping.get_overloads()
.Tillagd i version 3.13: Se PEP 702.
Tillgängliga kontexthanterare¶
- class warnings.catch_warnings(*, record=False, module=None, action=None, category=Warning, lineno=0, append=False)¶
En kontexthanterare som kopierar och, vid avslut, återställer varningsfiltret och funktionen
showwarning()
. Om argumentet record ärFalse
(standard) returnerar kontexthanterarenNone
vid inmatning. Om record ärTrue
returneras en lista som successivt fylls på med objekt som ses av en anpassadshowwarning()
-funktion (som också undertrycker utdata tillsys.stdout
). Varje objekt i listan har attribut med samma namn som argumenten tillshowwarning()
.Argumentet module tar en modul som kommer att användas istället för den modul som returneras när du importerar
warnings
vars filter kommer att skyddas. Detta argument finns främst för att testa själva modulenwarnings
.Om argumentet action inte är
None
, skickas de återstående argumenten tillsimplefilter()
som om det hade anropats direkt när det kom in i kontexten.Se Filtret för varningar för betydelsen av parametrarna category och lineno.
Anteckning
Se Samtidig säkerhet för kontexthanterare för detaljer om samtidighetssäkerheten för kontexthanteraren
catch_warnings
när den används i program som använder flera trådar eller asynkrona funktioner.Ändrad i version 3.11: Lagt till parametrarna action, category, lineno och append.
Samtidig säkerhet för kontexthanterare¶
Beteendet hos kontexthanteraren catch_warnings
beror på flaggan sys.flags.context_aware_warnings
. Om flaggan är true beter sig kontexthanteraren på ett concurrent-safe sätt och annars inte. Concurrent-safe innebär att den är både trådsäker och säker att använda inom asyncio coroutines och uppgifter. Att vara trådsäker innebär att beteendet är förutsägbart i ett flertrådat program. Flaggan är som standard true för fritt trådade program och false i annat fall.
Om flaggan context_aware_warnings
är false kommer catch_warnings
att ändra de globala attributen för modulen warnings
. Detta är inte säkert om det används i ett samtidigt program (med flera trådar eller asyncio coroutines). Om t.ex. två eller flera trådar använder klassen catch_warnings
samtidigt är beteendet odefinierat.
Om flaggan är true kommer catch_warnings
inte att ändra globala attribut och kommer istället att använda en ContextVar
för att lagra det nyligen etablerade filtreringstillståndet för varningar. En kontextvariabel ger trådlokal lagring och det gör användningen av catch_warnings
trådsäker.
Parametern record i kontexthanteraren beter sig också på olika sätt beroende på flaggans värde. När record är true och flaggan är false, fungerar kontexthanteraren genom att ersätta och senare återställa modulens showwarning()
-funktion. Det är inte simultansäkert.
När record är true och flaggan är true, ersätts inte funktionen showwarning()
. Istället indikeras inspelningsstatusen av en intern egenskap i kontextvariabeln. I detta fall kommer funktionen showwarning()
inte att återställas när kontexthanteraren avslutas.
Flaggan context_aware_warnings
kan ställas in med kommandoradsalternativet -X context_aware_warnings
eller med miljövariabeln PYTHON_CONTEXT_AWARE_WARNINGS
.
Anteckning
Det är troligt att de flesta program som vill ha ett trådsäkert beteende i varningsmodulen också vill sätta flaggan
thread_inherit_context
till true. Denna flagga gör att trådar som skapas avthreading.Thread
börjar med en kopia av kontextvariablerna från den tråd som startar den. När den är true kommer kontexten som etablerats avcatch_warnings
i en tråd även att gälla för nya trådar som startas av den. Om false, kommer nya trådar att starta med en tom warnings-kontextvariabel, vilket innebär att all filtrering som upprättades av encatch_warnings
-kontexthanterare inte längre kommer att vara aktiv.
Ändrad i version 3.14: Lade till sys.flags.context_aware_warnings
-flaggan och användningen av en kontextvariabel för catch_warnings
om flaggan är true. Tidigare versioner av Python agerade som om flaggan alltid var satt till false.