Ĉapitro 10 - Erarserĉado
Subtenu la Aŭtoro: Aĉeti la libron sur Amazono aŭ
la libro / ebook pakaĵo rekte Neniu amelo Gazetaro .
Legi la aŭtora aliaj liberaj Python libroj:
debugging
Nun ke vi scias suficxe por verki pli komplikaj programoj, vi komencas trovi ne-tiel-simplaj eraroj en ili.
Ĉi tiu ĉapitro kovras iuj iloj kaj teknikoj por trovi la radikon kaŭzo
de eraroj en via programo por helpi vin ripari bugs pli rapide kaj kun
malpli penado.
Por parafrazi malnova ŝerco inter programistoj, "Skribanta kodon konsistigas 90 procentojn de programado. Debugging kodo konsistigas la aliaj 90 procentoj. "
Via komputilo faros nur kion vi diros ĝin fari; ĝi ne legi vian menson kaj fari kion vi celas fari. Eĉ profesiaj programistoj krei misfunkciadojn tutan tempon, do ne sentas malinstigita se via programo havas problemon.
Feliĉe, estas kelkaj iloj kaj teknikoj por identigi kion ekzakte via kodo estas faranta kaj kie okazas erara. Unue, vi rigardos lignoproduktado kaj asertoj, du trajtoj kiuj povas helpi vin detekti misfunkciadojn frua. Ĝenerale, la pli frue vi kaptas cimoj, pli facila ili estos ripari.
Dua, vi rigardos kiel uzi la erarserĉilo.
La erarserĉilo estas karakterizaĵo de sencela kiu ekzekutas programon
unu instrukcion samtempe, donas al vi ŝancon por inspekti la valorojn en
variabloj dum via kodo kuras, kaj spuri kiel la valoroj ŝanĝas super la
kurso de via programo.
Tio estas multe pli malrapida ol kurante la programo al ĉiu rapido, sed
estas utila por vidi la efektivaj valoroj en programo dum ĝi kuras,
anstataŭ dedukti kion la valoroj povas esti de la fontkodo.
levante Esceptoj
Python levas escepto kiam provas ekzekuti nevalida kodon. En ĉapitro 3 , oni legas kiel manipuli Python esceptoj kun
try
kaj except
deklaroj tiel ke via programo povas rekuperi de esceptoj ke vi anticipis. Sed vi povas ankaŭ levi vian propran esceptoj en via kodo. Levante escepto estas maniero diri, "Haltu kurante la kodon en tiu funkcio kaj movi la programo ekzekuto por la except
aserto."
Esceptoj levigxas kun
raise
komunikaĵo. En kodo, kiel raise
deklaro konsistas el la sekvaj: - La
raise
ŝlosilvorto - Voko al la
Exception()
funkcio - Kordo kun helpema erarmesaĝon pasis al la
Exception()
funkcio
Ekzemple, tajpu la sekvajn en la interaga konko:
>>> Levi Escepto ( 'tio estas la erarmesaĝo.') Traceback (plej lasta alvoko lasta): Dosiero "<pyshell # 191>", linio 1, en <modulo> levi Escepto ( 'tio estas la erarmesaĝo.') Escepto: Jen la erarmesaĝon.
Se ne estas
try
kaj except
deklaroj kovrante la raise
deklaron kiu levis la escepton, la programo simple kraŝas kaj montras la escepto la erarmesaĝon.
Ofte ĝi estas la kodo kiu vokas la funkcio, la funkcio mem, kiu scipovas manipuli expection. Do vi komune vidi
raise
deklaro ene funkcio kaj la try
kaj except
deklaroj en la kodo nomante la funkcio. Ekzemple, malfermi novan dosieron redaktanto fenestro, tajpu la sekvan kodon kaj savi la programon kiel boxPrint.py: def boxPrint (simbolo, larĝo, alto): se len (simbolo)! = 1: ❶ levi Escepto ( 'Simbolo devas esti sola karaktero ŝnuro.') se larĝeco <= 2: ❷ levi Escepto ( 'Larĝo devas esti pli granda ol 2.) se alteco <= 2: ❸ levi Escepto ( 'Alteco devas esti pli granda ol 2.) print (simbolo * larĝo) por i en gamo (alteco - 2): print (simbolo + ( '' * (larĝeco - 2)) + simbolo) print (simbolo * larĝo) por SYM, w, h en (( '*', 4, 4), ( 'ho', 20, 5), (x, 1, 3), ( 'ZZ', 3, 3)): provu: boxPrint (SYM, w, h) ❹ krom Escepto kiel eraras: ❺ print ( 'Escepto okazis:' + str (err))
Tie ni difinis
boxPrint()
funkcio kiu prenas karakteron, anchura kaj alteco, kaj uzas la
karakteron por fari iom bildon de skatolo kun tiu larĝo kaj alteco. Tiu skatolo formo estas presita al la ekrano.
Ke ni volas la karakteron esti sola karaktero, kaj la larĝo kaj alteco estis pli granda ol 2. Ni aldonu
if
deklaroj levi esceptojn se tiuj kondiĉoj estas ne kontentigita. Poste, kiam ni vokas boxPrint()
kun diversaj argumentoj, nia try
/ except
manipulos nevalidaj argumentoj.
Ĉi programo uzas la
except Exception as err
formo de la except
aserto ❹. Se Exception
objekto revenis de boxPrint()
❶❷❸, tiu except
komunikaĵo konservos ĝin en variablo nomata err
. La Exception
objekto povas tiam esti konvertita al ĉeno de pasi ĝin al str()
por produkti uzantamika erarmesaĝo ❺. Kiam vi kuros ĉi boxPrint.py, la eligo aspektos tiel ĉi: **** * * * * **** OOOOOOOOOOOOOOOOOOOO OO OO OO OOOOOOOOOOOOOOOOOOOO Escepto okazis: Larĝeco devas esti pli granda ol 2. Escepto okazis: Simbolo devas esti sola karaktero ŝnuro.
Uzante la
try
kaj except
deklaroj, vi povas manipuli eraroj pli gracie anstataŭ lasanta la tutan programon akcidento. Ricevi la Traceback kiel String
Kiam Python renkontas eraro, ĝi produktas trezoro trove de eraro informo nomata traceback.
La traceback inkludas la erarmesaĝo, la linio numeron de la linio kiu
kaŭzis la eraro, kaj la sekvenco de la funkcio alvokoj kiuj kondukis al
la eraro. Tiu sekvenco de vokoj nomiĝas alvoko pilo.
Malfermi novan dosieron redaktanto fenestro en sencela, enigu la jenan programon, kaj konservi ĝin kiel errorExample.py:
def spamado (): lardo () def lardo (): levi Escepto ( 'tio estas la erarmesaĝo.') spamo()
Kiam vi kuros errorExample.py, la eligo aspektos tiel ĉi:
Traceback (plej lasta alvoko lasta): Dosiero "errorExample.py", linio 7, en <modulo> spamo() Dosiero "errorExample.py", linio 2, en spamon lardo () Dosiero "errorExample.py", linio 5, en lardo levi Escepto ( 'tio estas la erarmesaĝo.') Escepto: Jen la erarmesaĝon.
El la traceback, vi povas vidi ke la eraro okazis sur linio 5, en la
bacon()
funkcio. Tiu aparta alvoko al bacon()
venis de la linio 2, en la spam()
funkcio, kiu siavice estis nomita sur linio 7. En programoj kie
funkcioj povas nomi de multoblaj lokoj, la alvoko pilo povas helpi vin
determini kion nomi kaŭzis la eraro.
La traceback montriĝas per Python whenever levis escepto iras pluaj. Sed vi povas ankaŭ ricevi ĝin kiel kordo nomante
traceback.format_exc()
. Tiu funkcio estas utila, se vi volas la informojn de escepto de traceback sed ankaŭ volas except
deklaro al gracie manipuli la escepto. Vi bezonos importi Python traceback
modulo antaŭ nomi ĉi funkcio.
Ekzemple, anstataŭ frakasante via programo ĝuste kiam escepto okazas,
Vi povas skribi la traceback informon al efikado kaj teni vian programon
kurado. Vi povas rigardi la protokolodosiero poste, kiam vi pretas elpurigi via programo. Eniri la sekva en la interaga konko:
>>> Import traceback >>> Provo: levi Escepto ( 'tio estas la erarmesaĝo.') krom: errorFile = malfermita ( 'errorInfo.txt', 'w') errorFile.write (traceback.format_exc ()) errorFile.close () print ( 'La traceback info skribita al errorInfo.txt.') 116 La traceback info skribita al errorInfo.txt.
La
116
estas la reveno valoro de la write()
metodon, ekde 116 karakteroj estis skribitaj por la dosiero. La traceback teksto estis skribita al errorInfo.txt. Traceback (plej lasta alvoko lasta): Dosiero "<pyshell # 28>", linio 2, en <modulo> Escepto: Jen la erarmesaĝon.
asertoj
Aserto estas prudento ĉeko por certigi vian kodon ne faras ion evidente erara. Tiuj prudento ĉekojn estas plenumataj per
assert
deklaroj. Se la prudento ĉeko malsukcesas, tiam AssertionError
escepto levas. En kodo, ĝi assert
komunikaĵo konsistas el la sekvaj: - La
assert
ŝlosilvorto - Kondiĉo (te, esprimo kiu taksas al
True
aŭFalse
) - komo
- Kordo montri kiam la kondiĉo estas
False
Ekzemple, tajpu la sekvajn en la interaga konko:
>>> PodBayDoorStatus = 'malfermita' >>> Aserti podBayDoorStatus == 'malfermita', 'La guŝo golfeto pordoj devas esti "malfermita". >>> PodBayDoorStatus = 'I \ bedaŭras, Dave. Mi \ timas mi povas \ 't fari tion.' >>> Aserti podBayDoorStatus == 'malfermita', 'La guŝo golfeto pordoj devas esti "malfermita". Traceback (plej lasta alvoko lasta): Dosiero "<pyshell # 10>", linio 1, en <modulo> aserti podBayDoorStatus == 'malfermita', 'La guŝo golfeto pordoj devas esti "open". AssertionError: La guŝo golfeto pordoj devas esti "malfermita".
Tie ni starigis
podBayDoorStatus
al 'open'
, do de nun, ni plene atendis la valoro de tiu variablo esti 'open'
. En programo kiu uzas tiun variablon, ni skribis multajn kodo sub la supozo ke la valoro estas 'open'
eo kiu dependas ĝia estanta 'open'
por labori kiel ni atendis. Do ni aldonu aserto certigi ni pravas supozi podBayDoorStatus
estas 'open'
. Tie, ni inkludas la mesaĝon 'The pod bay doors need to be "open".'
Do estos facile vidi kion okazas se la aserto malsukcesas.
Poste, ke ni faru la evidenta eraro de asignanta
podBayDoorStatus
alian valoron, sed ne rimarkos ĝin inter multaj linioj de kodo. La aserto kaptas tiun eraron kaj klare diras al ni kio estas erara.
En simpla angla lingvo, oni
assert
komunikaĵo diras, "mi asertas ke ĉi tiu kondiĉo tenas vera, kaj se ne,
tie estas cimo ie en la programo." Kontraste esceptoj, via kodo devus pritrakti assert
deklaroj kun try
kaj except
; se assert
malsukcesas, via programo paneos.
Per malsukcesado rapida kiel ĉi, vi mallongigi la tempon inter la
origina kaŭzo de la eraro kaj kiam vi unue rimarkas la eraron. Tio reduktos la kvanton de kodo vi devas kontroli antaŭ trovi la kodon kiu kaŭzas la cimon.
Asertoj estas por programisto erarojn, ne uzanto eraroj.
Por eraroj kiuj povas esti reakirita de (ekzemple dosiero ne esti
trovita aŭ la uzanto eniri nevalida datumoj), levi escepto anstataŭ
detekti ŝin kun
assert
komunikaĵo. Uzante aserto en Traffic Light Simulado
Diru vi konstruado semaforo simulado programo. La datumstrukturo reprezentanta la stoplights ĉe intersekciĝo estas vortaro kun klavoj
'ns'
kaj 'ew'
, por la stoplights alfrontanta norde-sude kaj orient-okcidente, respektive. La valoroj ĉe tiuj klavoj estos unu el la kordoj 'green'
, ' yellow'
, aŭ 'red'
. La kodo aspektas tiel: market_2nd = { 'ns': 'verda', 'ew': 'ruĝa'} mission_16th = { 'ns': 'ruĝa', 'ew': 'verda'}
Tiuj du variabloj estos la intersekcoj de Market Street kaj 2nd Street kaj Mission Street kaj 16-a Strato. Komenci la projekton, vi volas skribi
switchLights()
funkcio, kiu prenos intersekciĝo vortaro kiel argumento kaj ŝanĝi la lumoj.
Unue vi eble pensas ke
switchLights()
devus simple ŝanĝi ĉiun lumon al la sekva koloro en la sekvenco: Ajna 'green'
valoroj devus ŝanĝi al 'yellow'
, 'yellow'
valoroj devus ŝanĝi al 'red'
kaj 'red'
valoroj devus ŝanĝi al 'green'
. La kodo por apliki tiun ideon povus aspekti kiel ĉi: def switchLights (haltlumon): por ŝlosila en stoplight.keys (): se haltlumon [klavo] == 'verda': haltlumon [klavo] = 'flava' elif haltlumon [klavo] == 'flava': haltlumon [klavo] = 'ruĝa' elif haltlumon [klavo] == 'ruĝa': haltlumon [klavo] = 'verda' switchLights (market_2nd)
Vi povas jam vidi la problemon kun tiu kodo, sed ni ŝajnigi vin skribis
la reston de la simulado kodo, miloj da linioj longaj, sen rimarki ĝin. Kiam vi fine fari kuri la simulado, la programo ne frakasi-sed via virtuala aŭtoj faras!
Ĉar vi jam skribis la resto de la programo, vi havas neniun ideon kie la cimo povis esti. Eble estas en la kodo simulante la aŭtoj aŭ en la kodo simulante la virtuala ŝoforoj. Ĝi povis preni horojn spuri la cimon al la
switchLights()
funkcio.
Sed se dum skribado
switchLights()
vi aldonis aserto kontroli ke almenaŭ unu el la lumoj estas ĉiam ruĝa, vi eble inkludis la sekvajn funde de la funkcio: aserti 'ruĝa' en stoplight.values (): Nek lumo estas ruĝa! '+ Str (haltlumon)
Kun tiu aserto en loko, via programo frakasus kun tiu eraro mesaĝo:
Traceback (plej lasta alvoko lasta): Dosiero "carSim.py", linio 14, en <modulo> switchLights (market_2nd) Dosiero "carSim.py", linio 13, en switchLights aserti 'ruĝa' en stoplight.values (): Nek lumo estas ruĝa! '+ Str (haltlumon) ❶ AssertionError: Nek lumo estas ruĝa! { 'Ns': 'flava', 'ew': 'verda'}
La grava linio tie estas la
AssertionError
❶.
Dum via programo plorkriado ne estas ideala, ĝi tuj atentigas ke
prudento ĉeko malsukcesis: Nek direkto de trafiko havas ruĝan lumon,
signifante ke trafiko povus iri ambaŭ vojojn. Per malsukcesado rapida frue programo ekzekuto, vi povas savi vin multan estonteco depuración penado. Malebligas asertoj
Asertoj povas esti malebligata pasante la
-O
opcion kiam kurante Python.
Tio estas bona por kiam vi finis skribi kaj testi vian programon kaj ne
deziras ĝin esti malrapidigita malsupren elfarante prudento ĉekojn
(kvankam plejofte assert
deklaroj ne kaŭzas konsiderindan rapidon diferenco). Asertoj estas por evoluo, ne la finan produkton. Kiam vi transdonu vian programon al iu alia kuri, ĝi devus esti libera de bugs kaj ne postulas la prudento ĉekoj. Vidu Appendix B por detaloj pri kiel lanĉi vian probable-ne-freneza programojn kun la -O
opcion. tala
Se vi iam metis
print()
komunikaĵo en via kodo por eligo iu variablo valoron dum via programo kuras, vi uzis formon de tala elpurigi vian kodon. Lignoproduktado estas granda vojo por kompreni kio okazas en via programo kaj en kio ordigi lian okazas. Python logging
modulo faciligas krei rekordon de kutimo mesaĝojn ke vi skribu.
Tiuj log mesaĝojn priskribos kiam la programo ekzekuto atingis la tala
funkcio alvokon kaj listo ajna variabloj vi specifita en tiu punkto en
tempo. Aliflanke, mankanta log mesaĝo indikas parton de la kodo estis ignorita kaj neniam ekzekutita. Uzante la tala Modulo
Ebligi la
logging
modulo montri log mesaĝojn sur via ekrano kiam via programo kuroj, kopiu la sekvan al la supro de via programo (sed sub la #! python
shebang linio): importado tala logging.basicConfig (nivelo = logging.DEBUG, formato = '% (asctime) s -% (levelname) s -% (Mesaĝo) s ')
Vi ne bezonas zorgi tro multe pri kiel tio funkcias, sed esence, kiam Python protokolojn okazaĵo, ĝi kreas
LogRecord
objekto kiu tenas informon pri tiu evento. La logging
modulo basicConfig()
funkcio permesas precizigi kion detaloj pri la LogRecord
objekton vi deziras vidi kaj kio vi deziras tiujn detalojn montrata.
Diru vi skribis funkcio por kalkuli la faktorialon de nombro. En matematiko, faktorialo 4 estas 1 × 2 × 3 × 4, aŭ 24. faktorialo 7 estas 1 × 2 × 3 × 4 × 5 × 6 × 7, aŭ 5,040. Malfermi novan dosieron redaktanto fenestro kaj eniri la sekvan kodon. Ĝi havas cimon en gxi, sed vi ankaŭ eniras plurajn log mesaĝojn por helpi vin mem eltrovi kio okazas erara. Savi la programon kiel factorialLog.py.
importado tala logging.basicConfig (nivelo = logging.DEBUG, formato = '% (asctime) s -% (levelname) s -% (Mesaĝo) s ') logging.debug ( 'Komenco de programo') def faktorialo (n): logging.debug ( 'Komenco de faktorialo (% s)'% (n)) tuta = 1 por i en gamo (n + 1): tuta * = i logging.debug ( 'i estas' + str (i) + ', entute estas' + str (entute)) logging.debug ( 'Fino de faktorialo (% s)'% (n)) reveno entute print (faktorialo (5)) logging.debug ( 'Fino de programo')
Tie, ni uzas la
logging.debug()
funkcio kiam ni volas presi ensaluti informon. Ĉi debug()
funkcio vokos basicConfig()
, kaj sxnuro de informo estos presitaj. Tiu informo estos en la formato ni specifita en basicConfig()
kaj inkluzivos la mesaĝojn ni pasis por debug()
. La print(factorial(5))
alvoko estas parto de la origina programo, tial la rezulto estas montrita eĉ se tala mesaĝoj estas malebligita.
La eligo de ĉi tiu programo aspektas jene:
2015-05-23 16: 20: 12.664 - DEBUG - Komenco de programo 2015-05-23 16: 20: 12.664 - DEBUG - Komenco de faktorialo (5) 2015-05-23 16: 20: 12.665 - DEBUG - i estas 0, entute estas 0 2015-05-23 16: 20: 12.668 - DEBUG - i estas 1, entute estas 0 2015-05-23 16: 20: 12.670 - DEBUG - i estas 2, tuta estas 0 2015-05-23 16: 20: 12.673 - DEBUG - i estas 3, entute estas 0 2015-05-23 16: 20: 12.675 - DEBUG - i estas 4, tuta estas 0 2015-05-23 16: 20: 12.678 - DEBUG - i estas 5 entute estas 0 2015-05-23 16: 20: 12,680 - DEBUG - Fino de faktorialo (5) 0 2015-05-23 16: 20: 12.684 - DEBUG - Fino de programo
La
factorial()
funkcio estas reveni 0
kiel la faktorialo de 5
, kiu estas en malvereco. La for
buklo devus esti multiplikante la valoro en total
de la nombroj de 1
al 5
. Sed la log mesaĝojn montrata per logging.debug()
montras ke la i
variablo komencas ĉe 0
anstataŭ 1
. Ekde nul fojojn io estas nulo, la resto de la ripetoj ankaŭ havas malĝustan valoron por total
. Ensalutanta mesaĝojn disponigi migrovojo de breadcrumbs kiuj povas helpi vin elkompreni kiam aferoj komencis iri malbone.
Ŝanĝi la
for i in range(n + 1):
linio for i in range(
1,
n + 1):
kaj kuri la programon denove. La eligo aspektos tiel ĉi: 2015-05-23 17: 13: 40.650 - DEBUG - Komenco de programo 2015-05-23 17: 13: 40.651 - DEBUG - Komenco de faktorialo (5) 2015-05-23 17: 13: 40.651 - DEBUG - i estas 1, entute estas 1 2015-05-23 17: 13: 40.654 - DEBUG - i estas 2, tuta estas 2 2015-05-23 17: 13: 40.656 - DEBUG - i estas 3, tuta estas 6 2015-05-23 17: 13: 40.659 - DEBUG - i estas 4, entute estas 24 2015-05-23 17: 13: 40.661 - DEBUG - i estas 5 entute estas 120 2015-05-23 17: 13: 40.661 - DEBUG - Fino de faktorialo (5) 120 2015-05-23 17: 13: 40.666 - DEBUG - Fino de programo
La
factorial(5)
alvoko ĝuste redonas 120
. La log mesaĝojn montris kio okazas interne la buklo, kiu kondukis rekte al la cimo.
Vi povas vidi ke la
logging.debug()
alvokoj presita eksteren ne nur la kordoj pasas al ili sed ankaŭ tempindiko kaj la vorto DEBUG. Ne debug kun presaĵo ()
Tajpadon
import logging
kaj logging.basicConfig(level=logging.DEBUG, format= '%(asctime)s - %(levelname)s - %(message)s')
estas iom maloportunaj. Vi povas deziri uzi print()
alvokas anstataŭ, sed ne donu al tiu tento! Iam vi faris depuración, vi finos elspezanta multan tempon forigante print()
alvokoj de via kodo por ĉiu log mesaĝo. Vi eble eĉ akcidente forigi iun print()
alvokoj kiuj estis uzitaj por nonlog mesaĝojn.
La bela afero pri log mesaĝojn estas ke vi libere povas plenigi vian
programon kun kiel multaj kiel vi ŝatas, kaj vi povas ĉiam malaktivigi
ilin poste aldonante sola logging.disable(logging.CRITICAL)
alvoko. Kontraste print()
, la logging
modulo faciligas ŝanĝi inter montrante kaj kaŝante log mesaĝojn.
Ensaluti mesaĝoj estas celita por la programisto, ne la uzanto. La uzanto ne zorgas pri la enhavo de iu vortaro valoron vi bezonas vidi por helpi kun debugging; uzi log mesaĝo por iu kiel tio. Por mesaĝoj kiuj la uzanto volas vidi, kiel Dosiero ne trovita aŭ Nevalida enigo, bonvolu enmeti numeron, vi devus uzi
print()
alvoko. Vi ne volas senigi la uzanto utilajn informojn post vi havas handikapita log mesaĝojn. tala Niveloj
Ensalutanta niveloj havigas vojon kategoriigi vian log mesaĝojn de graveco. Estas kvin tala niveloj, priskribitaj en Tabelo 10-1 el almenaŭ por plej gravaj. Mesaĝoj povas esti ensalutita en ĉiu nivelo uzante malsama tala funkcio.
Tabelo 10-1. Ensalutanta Niveloj en Python
nivelo
|
tala Funkcio
|
priskribo
|
---|---|---|
DEBUG
| logging.debug() |
La plej malalta nivelo. Uzata por malgrandaj detaloj. Kutime vi zorgas pri tiujn mesaĝojn nur kiam diagnozi problemojn.
|
INFO
| logging.info() |
Uzata por registri informojn pri ĝeneralaj eventoj en via programo aŭ konfirmi ke aferoj laboras ĉe ilia punkto en la programo.
|
AVERTO
| logging.warning() |
Uzas por indiki potenciala problemo kiu ne malhelpas la programo de laboro sed povus fari tion en la estonteco.
|
ERROR
| logging.error() |
Uzata por gravuri eraro kiu kaŭzis la programon malsukcesi fari ion.
|
MALTRANKVILIGAN
| logging.critical() |
La plej alta nivelo. Uzas por indiki fatala eraro kiu kaŭzis aŭ estas ronde kaŭzi la programo por halti kurante tute.
|
Via tala mesaĝo estas pasita kiel linio por tiuj funkcioj. La tala niveloj estas sugestoj. Finfine, ĝi estas ĝis vi decidi kiu kategorio via log mesaĝon falas en. Eniri la sekva en la interaga konko:
>>> Import tala >>> Logging.basicConfig (nivelo = logging.DEBUG, formato = '% (asctime) s - % (levelname) s -% (mesaĝo) s ') >>> Logging.debug ( 'Iu depuración detaloj.') 2015-05-18 19: 04: 26.901 - DEBUG - Iu depuración detaloj. >>> Logging.info ( 'La tala modulo funkcias.') 2015-05-18 19: 04: 35.569 - INFO - La tala modulo laboras. >>> Logging.warning ( 'Eraro mesaĝo estas ronde esti ensalutinta.) 2015-05-18 19: 04: 56.843 - AVERTO - Eraro mesaĝo estas ronde esti ensalutinta. >>> Logging.error ( 'Eraro okazis.') 2015-05-18 19: 05: 07.737 - ERROR - Eraro okazis. >>> Logging.critical ( 'La programo estas nekapabla reakiri!') 2015-05-18 19: 05: 45.794 - MALTRANKVILIGAN - La programo estas nekapabla reakiri!
Profito de tala niveloj estas ke vi povas ŝanĝi kion prioritato de tala mesaĝon vi volas vidi. Pasante
logging.DEBUG
la basicConfig()
funkcia level
ŝlosilvorto argumento montros mesaĝojn de ĉiuj tala niveloj (DEBUG esti la plej malalta nivelo). Sed post evoluantaj via programo pli, vi povas esti interesita nur en eraroj. En tiu kazo, vi povas agordi basicConfig()
's level
argumento por logging.ERROR
. Tio montros nur ERROR kaj MALTRANKVILIGAN mesaĝojn kaj transsaltu la Debug, INFO kaj AVERTO mesaĝojn. Malebligas Logging
Post vi elpurigita via programo, vi probable ne volas cxion cxi log mesaĝojn cluttering la ekrano. La
logging.disable()
funkcio preventas tiujn tiel ke vi ne devas iri en vian programon kaj forigi ĉiuj la tala alvokoj mane. Vi simple pasi logging.disable()
a tala nivelo, kaj ĝi tenas ĉiu log mesaĝojn al tiu nivelo aŭ pli malalta. Do se vi volas malebligi tala tute, nur aldonu logging.disable(logging.CRITICAL)
al via programo. Ekzemple, tajpu la sekvajn en la interaga konko: >>> Import tala >>> Logging.basicConfig (nivelo = logging.INFO, formato = '% (asctime) s - % (levelname) s -% (mesaĝo) s ') >>> Logging.critical ( 'Kritikaj eraro! Kritika eraro!) 2015-05-22 11: 10: 48.054 - MALTRANKVILIGAN - Kritika eraro! Kritika eraro! >>> Logging.disable (logging.CRITICAL) >>> Logging.critical ( 'Kritikaj eraro! Kritika eraro!) >>> Logging.error ( 'Eraro! Eraro!')
Ekde
logging.disable()
malebligos ĉiujn mesaĝojn post ĝi, vi kompreneble volas aldoni ŝin proksime de la import logging
linio de kodo en via programo. Tiel vi povas facile trovi ĝin komenti el aŭ uncomment ke alvoko por aktivigi aŭ malaktivigi tala mesaĝojn drajvo. Ensalutanta al Dosiero
Anstataŭ montri la protokolajn mesaĝojn al la ekrano, vi povas skribi ilin al teksta dosiero. La
logging.basicConfig()
funkcio prenas filename
ŝlosilvorto argumento, kiel tia: importado tala logging.basicConfig (dosiernomo = 'myProgramLog.txt', nivelo = logging.DEBUG, formato = ' % (Asctime) s -% (levelname) s -% (mesaĝo) s ')
La log mesaĝojn saviĝos al myProgramLog.txt. Dum ensalutanta mesaĝoj estas helpema, ili povas malordigi vian ekranon kaj fari malfacile legi la programo eligo.
Skribante la tala mesaĝojn al dosiero tenos vian ekranon klara kaj
stoki la mesaĝojn tiel vi povas legi ilin post kuri la programon. Vi povas malfermi tiun tekstdosiero en ajna tekstoredaktilo, kiel Notepad aŭ TextEdit.
Sencela la sencimigilo
La erarserĉilo estas karakterizaĵo de sencela kiu permesas ekzekuti vian programon unu linion je fojo. La erarserĉilo kuros sola linio de kodo kaj tiam atendos vin sciigi daŭrigi.
Per kurado via programo "sub la erarserĉilo 'kiel tio, vi povas preni
tiom multe tempon kiel vi volas ekzameni la valorojn en variabloj ĉe
ajna donita punkton dum la programo vivdaŭro. Tio estas valora ilo por spuri malsupren cimoj.
Ebligi sencela la erarserĉilo, klaku Debug ▸ sencimigilo en la interaga ŝelo fenestro. Ĉi Venigu la Debug Kontrolo fenestro, kiu aspektas kiel Figuro 10-1 .
Kiam la Debug Kontrolo fenestro aperas, elektu ĉiuj kvar el la Parva, Tieuloj, Fonto, kaj mallokajn variablojn markobutonojn por ke la fenestro montras la plenan aron de debug informo.
Dum la Debug Kontrolo fenestro montriĝas, ajna tempo vi kuras programon
de la dosiero redaktoro, la erarserĉilo estos paŭzi ekzekuto antaŭ la
unua instruado kaj montri la jenaj:
- La linio de kodo kiu estas ronde esti ekzekutita
- Listo de ĉiuj lokaj variabloj kaj iliaj valoroj
- Listo de ĉiuj tutmondaj variabloj kaj iliaj valoroj
Figuro 10-1. La Debug Kontrolo fenestro
Vi rimarkos ke en la listo de tutmondaj variabloj estas pluraj variabloj vi ne difinita, kiel
__builtins__
, __doc__
, __file__
, kaj tiel plu. Tiuj estas variabloj kiuj Python aŭtomate metas ĉiufoje ĝi kuras programon. La signifo de tiuj variabloj estas preter la kadro de tiu libro, kaj vi povas komforte ignori ilin.
La programo restos paŭzis ĝis vi premas unu el la kvin butonoj en la
Debug Kontrolo fenestro: Iru, Paŝo, Super, Ekstere, aŭ Quit.
iri
Klakante la Go butono kaŭzos la programon ekzekuti normale ĝis ĝi finiĝas aŭ atingas Haltpunkto.
(Breakpoints estas priskribita poste en tiu ĉapitro.) Se vi finis
depuración kaj volas ke la programo por daŭrigi kutime, klaku la Go butonon.
paŝo
Klakante la Paŝo butonon kaŭzi la erarserĉilo ekzekuti la sekvanta linio de kodo kaj tiam paŭzo denove. La Debug Kontrolo fenestro listo de tutmondaj kaj lokaj variabloj estos ĝisdatigita se iliaj valoroj ŝanĝas.
Se la sekvanta linio de kodo estas funkcio alvoko, la erarserĉilo estos
"eniri" ke funkcio kaj salti al la unua linio de kodo de tiu funkcio.
super
Klakante la Super butono ekzekuti la sekvanta linio de kodo, simila al la Paŝo butonon. Tamen, se la sekva linio de kodo estas funkcio alvoko, la Super butono "paŝi super" la kodon en la funkcio. La funkcio kodo lanĉiĝos plenrapide, kaj la erarserĉilo estos paŭzi kiam la funkcio alvoko revenas. Ekzemple, se la sekva linio de kodo estas
print()
alvoko, vi ne vere zorgas pri kodo ene la enkonstruita print()
funkcio; vi volas nur la kordoj pasas ŝin presita al la ekrano. Por tio, uzante la Super butono estas pli komuna ol la Paŝo butonon. eksteren
Klakante la Eksteren butono kaŭzos la erarserĉilo ekzekuti liniojn de kodo plenrapide ĝis ĝi revenas de la nuna funkcio. Se vi paŝis en funkcio alvoko kun la Paŝo butonon kaj nun simple volas teni ekzekuti instrukciojn ĝis vi revenas el, klaku El prembutonon "elpaŝi" de la nuna funkcio nomita.
Quit
Se vi volas halti elpurigi tute ne ĝenas daŭrigi ekzekuti la resto de la programo, klaku Quit butonon. La Quit butono tuj chesigi la programo. Se vi volas kuri via programo normale denove elektu Debug ▸ sencimigilo denove malŝalti la erarserĉilo.
Elpurigi la Nombro Aldonante Programo
Malfermi novan dosieron redaktanto fenestro kaj eniri la sekvan kodon:
presi ( 'Entajpu la unua numero aldoni:') unua = input () presi ( 'Entajpu la dua numero aldoni:') dua = input () presi ( 'Entajpu la trian numeron aldoni:') tria = input () print ( 'La sumo estas' + unua + dua + tria)
Konservi ĝin kiel buggyAddingProgram.py kaj ruli ĝin unua sen la erarserĉilo aktivigita. La programo volo eligo io tiamaniere:
Enigu la unuan numeron aldoni: 5 Entajpu la dua numero aldoni: 3 Entajpu la trian numeron aldoni: 42 La sumo estas 5342
La programo ne kraŝis, sed la sumo estas evidente erara. Ni ebligi la Debug Kontrolo fenestro kaj kuri ĝin denove, tiu tempon sub la erarserĉilo.
Kiam vi premas F5 aŭ elektu Run ▸ Run Modulo (kun Debug ▸ sencimigilo
ebligis kaj ĉiuj kvar markobutonojn en la Debug Kontrolo fenestro
kontrolis), la programo komenciĝas en paŭzis stato sur linio 1. La
erarserĉilo ĉiam paŭzo sur la linio de kodo estas pri ekzekuti. La Debug Kontrolo fenestro similos Figuro 10-2 .
Figuro 10-2. La Debug Kontrolo fenestro kiam la programo unua komenciĝas sub la erarserĉilo
Klaku Super butono iam ekzekuti la unua
print()
alvoko. Vi devus uzi Super anstataŭ Paŝo tie, ĉar vi ne volas eniri la kodon por la print()
funkcio.
La Debug Kontrolo fenestro ĝisdatigos al linio 2 kaj linio 2 en la
dosiero redaktanto fenestro estos reliefigita, kiel montrita en Figuro 10-3 . Tio montras al vi kie la programo ekzekuto nuntempe estas.
Figuro 10-3. La Debug Kontrolo fenestro post klako Super
Klaku denove por ekzekuti la
input()
funkcio alvokon, kaj la butonoj en la Debug Kontrolo fenestro malebligos sin dum sencela atendas vin tajpi ion por la input()
nomas en la interaga ŝelo fenestro. Entajpu 5
kaj gazetaro Reveno. La Debug Kontrolo fenestro butonoj estos reenabled.
Konservu klakanta Super, enirante
3
kaj 42
kiel la venontaj du nombroj, ĝis la erarserĉilo estas sur la linio 7, la fina print()
alvoko en la programo. La Debug Kontrolo fenestro devus aspekti Figuro 10-4 . Vi povas vidi en la mallokajn variablojn sekcio kiu la unua, dua, kaj tria variabloj havas inklinon al ŝnuro valoroj '5'
, '3'
kaj '42'
anstataŭ entjero valoroj 5
, 3
, kaj 42
. Kiam la lasta linio estas plenumata, tiuj kordoj estas kroĉitaj anstataŭ aldonita kune, kaŭzante la cimon.
Figuro 10-4. La Debug Kontrolo fenestro sur la lasta linio. La variabloj havas inklinon al kordoj, kaŭzante la cimon.
Tretante tra la programo kun la erarserĉilo estas helpema sed povas ankaŭ esti malrapida. Ofte vi volas ke la programo kuras kutime ĝis ĝi atingas certan linion de kodo. Vi povas agordi la erarserĉilo fari tion kun breakpoints.
breakpoints
A Haltpunkto povas stari sur la specifa linio de kodo kaj devigas la erarserĉilo paŭzi kiam ajn la programo ekzekuto atingas tiun linion. Malfermi novan dosieron redaktanto fenestro kaj eniri la sekvan programon, kiu simulas klakanta monero 1,000 fojojn. Konservi ĝin kiel coinFlip.py.
importado hazarda kapojn = 0 por i en gamo (1, 1001): ❶ se random.randint (0, 1) == 1: kapojn = kapoj + 1 se i == 500: ❷ print ( 'Duonvoje faris!) print ( 'Kapoj venadis' + str (kapoj) + 'tempoj.)
La
random.randint(0, 1)
nomas ❶ revenos 0
duono de la tempo kaj 1
la alian duonon de la tempo. Tio povas esti uzita por simuli 50/50 monero flip kie 1
reprezentas kapoj. Kiam vi kuros ĉi programo sen la erarserĉilo, ĝi rapide eligas ion kiel la sekvanta: Duonvoje farita! Spikoj elkreskis 490 fojojn.
Se vi kuris tiu programo sub la erarserĉilo, vi devus klaki la Super butono miloj da fojoj antaŭ la programo finiĝis. Se vi estus interesita en la valoro de
heads
ĉe la duonpunkto de la programo ekzekuto, kiam 500 el 1000 monero
klakas estis kompletigita, vi povus anstataŭe simple agordi Haltpunkto
sur la linio print('Halfway done!')
❷. Agordi Haltpunkto, dekstra-klaki la linio en la dosiero redaktoro kaj elekti Ara Haltpunkto, kiel montrita en Figuro 10-5 .
Figuro 10-5. Metante Haltpunkto
Vi ne volas agordi Haltpunkto sur la
if
komunikaĵo linio, ekde la if
komunikaĵo estas ekzekutita sur ĉiu unuopa ripeto tra la buklo. Per opcio la Haltpunkto sur la kodo en la if
komunikaĵo, la erarserĉilo rompas nur kiam la ekzekuto eniras la if
klaŭzo.
La linion kun la Haltpunkto estos elstarigitaj en flava en la dosiero redaktoro. Kiam vi kuras la programon sub la erarserĉilo, ĝi komencos en paŭzis stato ĉe la unua linio, kiel kutime. Sed se vi klakas Iru, la programo kuros plenrapide ĝis ĝi atingas la linion kun la Haltpunkto surtabligis ĝin. Vi povas alklaki Iru Super, Ŝtupo, aŭ El daŭrigi kiel normala.
Se vi volas forigi Haltpunkto, dekstra-klaki la linio en la dosiero redaktoro kaj elekti Klara Haltpunkto el la menuo. La flava kolorigo foriros, kaj la erarserĉilo ne rompu sur tiu linio en la estonteco.
resumo
Asertoj, esceptoj, lignoproduktado kaj la erarserĉilo estas ĉiuj valoraj iloj por trovi kaj malhelpi eraroj en via programo. Asertojn kun la Python
assert
aserto estas bona maniero por apliki "prudento ĉekojn" kiuj donas vin frua averto kiam necesa kondiĉo ne teni vera. Asertoj estas nur por eraroj, ke la programo ne klopodi rekuperi de kaj fali rapide. Alie, vi devus levi escepto.
Escepto eblas kaptitaj kaj manipulita de la
try
kaj except
deklaroj. La logging
modulo estas bona maniero por rigardi en vian kodon dum ĝi kuras kaj estas multe pli oportuna al uzi ol la print()
funkcion pro lia malsama tala niveloj kaj kapableco por ensaluti al tekstdosiero.
La erarserĉilo permesas paŝi tra via programo linio samtempe. Alternative,
vi povas kuri via programo ĉe normala rapideco kaj havas la erarserĉilo
paŭzo ekzekuto kiam ajn ĝi atingas linion kun Haltpunkto aro. Uzanta la erarserĉilo, vi povas vidi la staton de iu variablo estas valoro ĉe ajna punkto dum la programo vivdaŭro.
Tiuj debugging iloj kaj teknikoj helpos vin skribi programojn kiuj funkcius. Akcidente enkonduki cimoj en via kodo estas fakto de vivo, kiel ajn multaj jaroj de kodigo sperto vi havas.
praktiko Demandoj
Q:
|
1. Skribi la
assert deklaro ke deĉenigas AssertionError se la variablo spam estas entjero malpli ol 10 . |
Q:
|
2. Skribu al
assert deklaro ke deĉenigas AssertionError se la variabloj eggs kaj bacon enhavas kordoj kiuj estas la sama kiel ĉiu alia, eĉ se iliaj kazoj estas malsamaj (te, 'hello' kaj 'hello' estas konsideritaj la sama, kaj 'goodbye' kaj 'GOODbye' ankaŭ konsideris la sama). |
Q:
|
3. Skribu al
assert deklaro ke ĉiam deĉenigas AssertionError . |
Q:
|
4. Kio estas la du linioj kiuj via programo devas havi por povi nomi
logging.debug() ? |
Q:
|
5. Kio estas la du linioj kiuj via programo devas havi por havi
logging.debug() sendos tala mesaĝon al dosiero nomita programLog.txt ? |
Q:
|
6. Kio estas la kvin tala niveloj?
|
Q:
|
7. Kio linio de kodo vi povas aldoni malŝalti ĉiuj tala mesaĝojn en via programo?
|
Q:
|
8. Kial uzas tala mesaĝojn bona ol uzi
print() por montri la sama mesaĝo? |
Q:
|
9. Kio estas la diferencoj inter la Paŝo, Super kaj Eksteren butonoj en la Debug Kontrolo fenestro?
|
Q:
|
10. Post vi klaku Iru en la Debug Kontrolo fenestro, kiam estos la erarserĉilo haltigi?
|
Q:
|
11. Kio estas Haltpunkto?
|
Q:
|
12. Kiel vi agordi Haltpunkto sur linio de kodo en sencela?
|
praktiko Projekto
Por praktiko, skribi programon kiu faras la sekvan.
Debugging Coin Toss
La jenaj programo celas esti simpla monero ĵeton diveni ludo. La ludanto ricevas du divenoj (estas facila ludo). Tamen, la programo havas plurajn erarojn en ĝi. Kuri tra la programo kelkajn fojojn por trovi la erarojn kiuj observas la programo de laboranta ĝuste.
importado hazarda diveni = '' dum diveni ne en ( 'kapoj', 'vostoj'): print ( 'Divenu la moneron ĵeti! Enter kapoj aŭ vostoj) diveni = input () ĵeti = random.randint (0, 1) # 0 estas vostoj, 1 estas kapoj se ĵeton == diveno: presi ( 'Vi havas ĝin! ") alie: print ( 'Nope! Divenu denove!) guesss = input () se ĵeton == diveno: presi ( 'Vi havas ĝin! ") alie: print ( 'Nope. Vi estas vere malbona ĉe tiu ludo.)
Nenhum comentário:
Postar um comentário