Python-utvecklingsläge¶
Tillagd i version 3.7.
Python Development Mode introducerar ytterligare körtidskontroller som är för dyra för att aktiveras som standard. Det bör inte vara mer mångordigt än standardvärdet om koden är korrekt; nya varningar utfärdas endast när ett problem upptäcks.
Det kan aktiveras med kommandoradsalternativet -X dev
eller genom att ställa in miljövariabeln PYTHONDEVMODE
till 1
.
Se även Python debug build.
Effekter av Pythons utvecklingsläge¶
Aktivering av Python Development Mode liknar följande kommando, men med ytterligare effekter som beskrivs nedan:
PYTHONMALLOC=debug PYTHONASYNCIODEBUG=1 python -W default -X faulthandler
Effekter av Pythons utvecklingsläge:
Lägg till
default
warning filter. Följande varningar visas:Normalt filtreras ovanstående varningar med standard warning filters.
Det beter sig som om kommandoradsalternativet
-W default
används.Använd kommandoradsalternativet
-W error
eller sätt miljövariabelnPYTHONWARNINGS
tillerror
för att behandla varningar som fel.Installera felsöknings-hooks på minnesallokatorer för att kontrollera:
Underflöde i buffert
Buffertöverfyllnad
Överträdelse av API för minnesallokering
Osäker användning av GIL
Se C-funktionen
PyMem_SetupDebugHooks()
.Det beter sig som om miljövariabeln
PYTHONMALLOC
är inställd pådebug
.För att aktivera Python Development Mode utan att installera debug-hooks på minnesallokatorer, ställ in miljövariabeln
PYTHONMALLOC
tilldefault
.Anropa
faulthandler.enable()
vid Python-start för att installera hanterare för signalernaSIGSEGV
,SIGFPE
,SIGABRT
,SIGBUS
ochSIGILL
för att dumpa Python-traceback vid en krasch.Det beter sig som om kommandoradsalternativet
-X faulthandler
används eller om miljövariabelnPYTHONFAULTHANDLER
är satt till1
.Aktivera asyncio felsökningsläge. Till exempel kontrollerar
asyncio
om det finns coroutines som inte var väntade och loggar dem.Det beter sig som om miljövariabeln
PYTHONASYNCIODEBUG
är inställd på1
.Kontrollera argumenten encoding och errors för strängkodnings- och avkodningsoperationer. Exempel:
open()
,str.encode()
ochbytes.decode()
.Som standard, för bästa prestanda, kontrolleras errors-argumentet endast vid det första kodnings-/avkodningsfelet och encoding-argumentet ignoreras ibland för tomma strängar.
Destruktorn för
io.IOBase
loggarclose()
undantag.
I Pythons utvecklingsläge aktiveras inte modulen tracemalloc
som standard, eftersom kostnaden (för prestanda och minne) skulle bli för stor. Om du aktiverar modulen tracemalloc
får du ytterligare information om ursprunget till vissa fel. Till exempel loggar ResourceWarning
spårningen där resursen allokerades, och ett buffer overflow-fel loggar spårningen där minnesblocket allokerades.
Python Development Mode hindrar inte kommandoradsalternativet -O
från att ta bort assert
-satser eller från att sätta __debug__
till False
.
Pythons utvecklingsläge kan endast aktiveras när Python startas. Dess värde kan läsas från sys.flags.dev_mode
.
Ändrad i version 3.8: Destruktorn io.IOBase
loggar nu close()
-undantag.
Ändrad i version 3.9: Argumenten encoding och errors kontrolleras nu för kodning och avkodning av strängar.
Exempel på ResourceWarning¶
Exempel på ett skript som räknar antalet rader i den textfil som anges på kommandoraden:
import sys
def main():
fp = open(sys.argv[1])
nlines = len(fp.readlines())
print(nlines)
# The file is closed implicitly
if __name__ == "__main__":
main()
Skriptet stänger inte filen explicit. Som standard ger Python inte ut någon varning. I exemplet används README.txt, som har 269 rader:
$ python script.py README.txt
269
Om du aktiverar Python Development Mode visas en ResourceWarning
-varning:
$ python -X dev script.py README.txt
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
Om du aktiverar tracemalloc
visas dessutom den rad där filen öppnades:
$ python -X dev -X tracemalloc=5 script.py README.rst
269
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='README.rst' mode='r' encoding='UTF-8'>
main()
Object allocated at (most recent call last):
File "script.py", lineno 10
main()
File "script.py", lineno 4
fp = open(sys.argv[1])
Lösningen är att stänga filen explicit. Exempel med hjälp av en kontexthanterare:
def main():
# Close the file explicitly when exiting the with block
with open(sys.argv[1]) as fp:
nlines = len(fp.readlines())
print(nlines)
Att inte stänga en resurs explicit kan lämna en resurs öppen mycket längre än förväntat; det kan orsaka allvarliga problem när Python avslutas. Det är illa i CPython, men det är ännu värre i PyPy. Att stänga resurser explicit gör en applikation mer deterministisk och mer tillförlitlig.
Exempel på fel i dålig filbeskrivare¶
Skriptet visar den första raden av sig själv:
import os
def main():
fp = open(__file__)
firstline = fp.readline()
print(firstline.rstrip())
os.close(fp.fileno())
# The file is closed implicitly
main()
Som standard ger Python inte ut någon varning:
$ python script.py
import os
Python Development Mode visar en ResourceWarning
och loggar ett ”Bad file descriptor”-fel när filobjektet slutförs:
$ python -X dev script.py
import os
script.py:10: ResourceWarning: unclosed file <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
main()
ResourceWarning: Enable tracemalloc to get the object allocation traceback
Exception ignored in: <_io.TextIOWrapper name='script.py' mode='r' encoding='UTF-8'>
Traceback (most recent call last):
File "script.py", line 10, in <module>
main()
OSError: [Errno 9] Bad file descriptor
os.close(fp.fileno())
stänger filbeskrivaren. När filobjektets slutbehandlare försöker stänga filbeskrivaren igen misslyckas den med felet Bad file descriptor
. En file descriptor får bara stängas en gång. I värsta fall kan det leda till en krasch om den stängs två gånger (se bpo-18748 för ett exempel).
Lösningen är att ta bort raden os.close(fp.fileno())
eller öppna filen med closefd=False
.