Ачааллж байна...
Энэ сургалтын туршид бид traceback-уудыг олон удаа уншсан. 6.1 дүгээр хичээлд ZeroDivisionError-ийн хоёр давхар traceback, 7.4 дүгээр хичээлд pytest-ийн хэлбэрийн уналт, 9.3 дугаар хичээлд KeyError. Эдгээр нь бүгд богино, ойлгомжтой байсан: алдаа гарсан газар ба шалтгаан нь ойрхон. Бодит программд traceback ихэвчлэн урт байдаг. Алдаа олон файл, олон функцийг дамжиж гарч, хамгийн доод мөр нь танд огт хамаагүй мэт газрыг зааж, шалтгаан нь огт өөр газар нуугддаг. Энэ хичээл бол энэ сургалтын хамгийн гүнзгий алдаа уншилт: гурван файлыг дамжсан дөрвөн давхар traceback-ийг давхар бүрээр нь, монголоор бүрэн уншина.
Хичээлийн гол санаа бол нэг ялгаа: алдаа хаана гарсан ба алдаа хаана үүссэн. Traceback эхнийхийг маш нарийн хэлдэг, харин хоёр дахийг нь хэзээ ч шууд хэлдэггүй. Бид traceback-аас нотлох баримт цуглуулж, 10.1 дүгээр хичээлийн мөрдөгчийн аргаар жинхэнэ шалтгааныг олж, түүнийг эх үүсвэр дээр нь засна. Дараа нь гинжилсэн алдааны traceback, Python-ий стандарт сан болон package-уудын дундуур дамждаг traceback-ийг уншина. Бид pytest-dadlaga фолдерт ажиллана.
Нэг газраас илгээсэн илгээмж эвдэрч ирлээ гэж бодоорой. Илгээмж бүрт замын баримт хавсаргасан байдаг: аль салбараас аль салбар руу, хэн хүлээн авч, хэнд шилжүүлсэн. Сүүлийн мөрөнд "хүлээн авагч илгээмжийг нээхэд шил хагарсан байсан" гэж бичигдсэн. Хамгийн хялбар дүгнэлт нь хүлээн авагчийг буруутгах. Гэхдээ ухаалаг шалгагч замын баримтыг доороос нь дээш уншина: хүлээн авагчийн өмнө хүргэгч, түүний өмнө ангилах төв, түүний өмнө анхны салбар. Тэгээд асууна: шил хаана хагарсан бэ? Магадгүй хүргэлтийн үеэр, магадгүй ангилах төвд, эсвэл магадгүй илгээгч анхнаасаа шилийг сайн боогоогүй.
Traceback бол яг ийм замын баримт. Сүүлийн мөр нь алдаа илэрсэн газар: шил хагарснаа мэдсэн мөч. Түүний дээрх давхар бүр нь өмнөх зогсоол: аль функц аль функцийг дуудсан. Алдаа илэрсэн газар ихэвчлэн алдаа үүссэн газар биш. Замын баримтыг доороос дээш уншиж, давхар бүрт "алдаа энд үүссэн байж болох уу" гэж асууснаар л жинхэнэ шалтгаан руу хүрнэ. Мөн нэг чухал нарийн зүйл бий: замын баримт зөвхөн илгээмжийн замыг харуулдаг, шил хаанаас ирснийг харуулдаггүй. Энэ санаа хичээлийн гол нээлт болно.
Хэргийн газрыг бэлдэх
VS Code-д pytest-dadlaga фолдероо нээж, venv идэвхтэй эсэхийг шалгаарай. Хэн нэгэн баримтын барааны файлыг Notepad-аар гараар засварласан гэж бодъё. Үндсэн фолдерт items.json нэртэй файлыг VS Code-д үүсгэж, дараахыг бичнэ үү.
json
[
["талх", "2000", 2],
["сүү", 3000, 1]
]Анхааралтай хараарай: талхны үнэ “2000” гэж хашилтад бичигдсэн, сүүнийх 3000 гэж хашилтгүй. Гараар засварлахад ийм алдаа маш амархан гардаг. Одоохондоо үүнийг "мэдэхгүй" мэт дүр эсгэе. Дараа нь үндсэн фолдерт report_app.py нэртэй script үүсгэнэ үү.
python
from receipt import receipt_text
from storage import load_items
items = load_items("items.json")
print(receipt_text(items))Энэ script 9.1 дүгээр хичээлийн load_items, 9.2 дугаар хичээлийн receipt_text-ийг ашиглаж, файлаас баримт уншиж хэвлэнэ.
Command:
python report_app.pyГаралт:
Traceback (most recent call last):
File "C:\Users\Bat\pytest-dadlaga\report_app.py", line 5, in <module>
print(receipt_text(items))
~~~~~~~~~~~~^^^^^^^
File "C:\Users\Bat\pytest-dadlaga\receipt.py", line 15, in receipt_text
lines = receipt_lines(items)
File "C:\Users\Bat\pytest-dadlaga\receipt.py", line 11, in receipt_lines
return [f"{name} x{qty}: {format_price(price * qty)}" for name, price, qty in items]
~~~~~~~~~~~~^^^^^^^^^^^^^
File "C:\Users\Bat\pytest-dadlaga\prices.py", line 6, in format_price
return f"{amount:,}₮"
ValueError: Cannot specify ',' with 's'.Дөрвөн давхар, гурван файл. Өмнөх хичээлүүдийн бүх traceback-аас урт. Сандрах хэрэггүй: бид түүнийг давхар бүрээр нь, доороос нь дээш уншина. Таны мөрийн дугаарууд файлуудын бүтцээс хамаараад өөр байж болно, мөн “~” ба “^” тэмдгүүд Python-ий хувилбараас хамаараад өөр байрлалтай, эсвэл огт байхгүй байж болно. Шинэ Python-ий хувилбарууд terminal-д traceback-ийг өнгөөр ч ялгаж харуулдаг.
Эхлээд: гарчиг
Хамгийн дээд мөр “Traceback (most recent call last):” нь "Мөрдлөг (хамгийн сүүлийн дуудлага хамгийн сүүлд)" гэсэн утгатай. Энэ мөр бүхэл traceback-ийг хэрхэн унших түлхүүрийг өгч байна: давхрууд цаг хугацааны дарааллаар жагссан, хамгийн дээд нь хамгийн эхний дуудлага, хамгийн доод нь хамгийн сүүлийн, алдаа гарах мөчид идэвхтэй байсан дуудлага. Тиймээс доороос эхэлж уншина: тэнд алдааны хамгийн ойрын нотлох баримт бий.
Хамгийн доод мөр: юу болсон бэ
“ValueError: Cannot specify ‘,’ with ‘s’.” Алдааны төрөл ValueError, мессеж нь “‘,’ тэмдгийг ‘s’-тэй хамт заах боломжгүй”. Энэ мессежийг 7.4 дүгээр хичээлд format_price-д текст өгөхөд харсан. “s” бол f-string-ийн текстийн формат. Мессеж маш тодорхой юм хэлж байна: мянгатын таслал тавих гэж оролдсон утга нь тоо биш, текст байсан. Энэ бол бидний анхны нотлох баримт, өмнөх туршлагаас шууд таньсан.
4-р давхар: алдаа гарсан газар
File "C:\Users\Bat\pytest-dadlaga\prices.py", line 6, in format_price
return f"{amount:,}₮"Давхар бүр хоёр мөртэй. Эхний мөр гурван мэдээлэл өгнө: файлын бүтэн зам, мөрийн дугаар, функцийн нэр. “prices.py файлын 6 дугаар мөр, format_price функцийн дотор”. Хоёр дахь мөр бол тэр мөрийн код өөрөө. Энэ бол алдаа гарсан яг газар: f-string amount-ийг мянгатын таслалтай хэвлэх гэж оролдоход алдаа гарсан. Дээрх нотлох баримттай нийлүүлбэл: format_price-д amount гэж текст ирсэн.
Энд мөрдөгчийн хамгийн чухал асуулт: format_price бол буруутан уу? Үгүй. format_price тоо хүлээдэг бөгөөд 7.3, 8.3 дугаар хичээлүүдийн хүснэгт бүхий тестүүдээр тоонд зөв ажилладаг нь батлагдсан. Тэр буруу утга хүлээн авсан, хүлээн авагч шилийг хагарсан байдалтай олсон. Асуулт нь: тэр текст хаанаас ирсэн бэ? Нэг давхар дээш.
3-р давхар: хэн буруу утга өгсөн бэ
File "C:\Users\Bat\pytest-dadlaga\receipt.py", line 11, in receipt_lines
return [f"{name} x{qty}: {format_price(price * qty)}" for name, price, qty in items]
~~~~~~~~~~~~^^^^^^^^^^^^^receipt.py-ийн 11 дүгээр мөр, receipt_lines функц. Энэ мөр урт, гэхдээ доорх тэмдгүүд аль хэсгийг онож байгааг заажээ: “~” ба “^” нь format_price(price * qty) хэсгийн доор байна. Энд format_price-ийг price * qty-ийн үр дүнгээр дуудсан. Тэгэхээр price * qty текст гаргасан. Яаж? Тоог тоогоор үржүүлбэл тоо гарна. Гэхдээ Python-д текстийг тоогоор үржүүлж болдог бөгөөд үр дүн нь давтагдсан текст. Үүнийг шалгая.
Command:
python -c "print('2000' * 2)"Гаралт:
20002000Текст “2000”-ийг 2-оор үржүүлэхэд 4000 биш, “20002000” гарлаа: текст хоёр удаа залгагдсан. Хэрвээ price нь “2000” гэсэн текст байсан бол price * qty нь “20002000” гэсэн текст болж, format_price түүнд таслал тавих гэж оролдоод унасан. Бүх нотлох баримт нэг таамаглал руу зааж байна: price нь тоо биш, текст. Гэхдээ receipt_lines ч буруутан биш: тэр items-ээс авсан утгыг ашигласан. Асуулт улам дээшилж байна: items хаанаас ирсэн бэ?
2-р давхар
File "C:\Users\Bat\pytest-dadlaga\receipt.py", line 15, in receipt_text
lines = receipt_lines(items)receipt.py-ийн 15 дугаар мөр, receipt_text функц. Энэ давхар зүгээр л items-ийг receipt_lines руу дамжуулсан. Энд ямар ч тооцоолол, өөрчлөлт байхгүй: зам дамжуулагч зогсоол. Шилжүүлэхээс өөр юу ч хийгээгүй салбар.
1-р давхар: эхлэл
File "C:\Users\Bat\pytest-dadlaga\report_app.py", line 5, in <module>
print(receipt_text(items))
~~~~~~~~~~~~^^^^^^^report_app.py-ийн 5 дугаар мөр. “<module>“ гэсэн нэр нь энэ код ямар ч функцийн дотор биш, файлын үндсэн түвшинд байгааг заана. Энэ бол бидний эхлүүлсэн script, замын эхний салбар. Энд receipt_text-ийг items-ээр дуудсан.
Traceback-д юу байхгүй вэ
Одоо энэ хичээлийн гол нээлт. Бид бүх давхрыг уншлаа: report_app.py, receipt_text, receipt_lines, format_price. Гэхдээ items-ийн price хаанаас текст болж ирсэн бэ? report_app.py-ийн 4 дүгээр мөрийг хараарай: items = load_items("items.json"). items-ийг load_items үүсгэсэн. Гэтэл load_items traceback-д огт байхгүй.
Учир нь traceback зөвхөн алдаа гарах мөчид идэвхтэй байсан дуудлагуудыг харуулдаг. load_items аль хэдийн ажиллаж дуусаад, items-ийг буцаасан. Алдаа гарах үед тэр нь стект байгаагүй. 10.2 дугаар хичээлийн CALL STACK-ийг санаарай: стек бол "одоо хэн хэнийг дуудаж байна" гэсэн зураглал, "өмнө нь юу болсон" биш. Зүйрлэлээр бол замын баримт илгээмжийн замыг харуулдаг, харин шил хэдийнээс хагарах нөхцөлтэй байсныг, анхны савлагааг харуулдаггүй. Traceback дуудлагын замыг харуулдаг, өгөгдлийн замыг харуулдаггүй.
Тиймээс traceback-ийн дээд хэсэгт хүрээд зогсохгүй, "энэ буруу утга хаанаас ирсэн бэ" гэсэн асуултыг өгөгдлийн замаар үргэлжлүүлнэ. items-ийг load_items үүсгэсэн, load_items items.json-оос уншсан. Шалгая.
Command:
python -c "from storage import load_items; print(load_items('items.json'))"Гаралт:
[('талх', '2000', 2), ('сүү', 3000, 1)]Хоёр үнийг харьцуулаарай: ‘2000’ хашилтанд, 3000 хашилтгүй. 10.1 дүгээр хичээлд ярьсан !r хэлбэрийн давуу тал энд харагдаж байна: print жагсаалтыг хэвлэхэд элемент бүрийг код хэлбэрээр харуулдаг тул текст хашилттай, тоо хашилтгүй. Талхны үнэ текст. Эх үүсвэр олдлоо: алдаа items.json файлд, хүн гараар засахдаа хашилт нэмсэн газар. Алдаа prices.py-д илэрсэн, гэхдээ өгөгдлийн файлд үүссэн. Дөрвөн давхар traceback болон нэг өгөгдлийн алхмаар бид замын баримтыг бүхэлд нь мөшгөлөө.
Хоёр түвшний засвар
Одоо засах цаг. Хамгийн шууд засвар нь items.json-д хашилтыг устгах. Энэ нь яг одоогийн асуудлыг шийднэ. Гэхдээ 10.1 дүгээр хичээлийн "шалтгааныг нь зас" гэсэн зарчмаар асуугаарай: хэн нэгэн маргааш дахин гараар засаад өөр хашилт нэмбэл яах вэ? Дахин дөрвөн давхар traceback, дахин мөрдөлт.
Илүү гүн засвар бол өгөгдөл программ руу орж ирэх ирмэг дээр шалгалт тавих явдал. 8.4 дүгээр хичээлийн apply_discount, 9.3 дугаар хичээлийн make_expense буруу оролтыг эсэргүүцдэг байсныг санаарай. Гадаад ертөнцөөс, файл, хэрэглэгч, сүлжээнээс ирж буй өгөгдлийг ирсэн даруйд нь шалгах нь алдааг үүссэн газарт нь барьдаг. 9.2 дугаар хичээлийн "ирмэг" санаатай яг таарч байна: гаж нөлөө, тэр дундаа файл унших нь ирмэг дээр, мөн шалгалт ч тэнд.
storage.py-д load_items-ийг дараах байдлаар өөрчилнө үү.
python
def load_items(path):
with open(path, encoding="utf-8") as f:
items = [tuple(item) for item in json.load(f)]
for i, (name, price, qty) in enumerate(items):
if not isinstance(price, int):
raise ValueError(f"Item {i}: price must be a number, got {price!r}")
return itemsenumerate() бараа бүрийн дугаарыг өгнө, isinstance() үнэ бүхэл тоо эсэхийг шалгана. Хэрвээ биш бол алдааны мессеж аль бараа, ямар утга асуудалтайг яг хэлнэ. {price!r} нь утгыг хашилттайгаар харуулдаг тул текст гэдэг нь мессежээс шууд харагдана.
Command:
python report_app.pyГаралт:
Traceback (most recent call last):
File "C:\Users\Bat\pytest-dadlaga\report_app.py", line 4, in <module>
items = load_items("items.json")
File "C:\Users\Bat\pytest-dadlaga\storage.py", line 14, in load_items
raise ValueError(f"Item {i}: price must be a number, got {price!r}")
ValueError: Item 0: price must be a number, got '2000'Шинэ traceback-ийг өмнөхтэй харьцуулаарай. Дөрвөн давхар хоёр болсон. Хамгийн доод мөр одоо “Cannot specify ‘,’ with ‘s’” гэсэн нууцлаг мессеж биш, “Item 0: price must be a number, got ‘2000’” буюу “0 дүгээр бараа: үнэ тоо байх ёстой, ‘2000’ ирсэн” гэсэн тодорхой мессеж. 2-р давхар load_items-ийг, өгөгдөл орж ирсэн яг газрыг заана. Алдаа одоо үүссэн газартаа илэрч байна. Хэн ч энэ мессежийг хараад мөрдөлт хийлгүйгээр items.json-ийн эхний барааг засна.
Одоо items.json-оос “2000”-ийн хашилтыг устгаж хадгална уу.
Command:
python report_app.pyГаралт:
талх x2: 4,000₮
сүү x1: 3,000₮
Нийт: 7,700₮Тестээр хамгаалах
10.1 дүгээр хичээлийн зургаа дахь алхам: засаад, тестээр батал. tests\test_storage.py-ийн төгсгөлд 9.1 болон 8.4 дүгээр хичээлүүдийн аргаар тест нэмнэ үү.
python
def test_load_rejects_text_price(tmp_path):
path = tmp_path / "items.json"
path.write_text('[["талх", "2000", 2]]', encoding="utf-8")
with pytest.raises(ValueError, match="price must be a number"):
load_items(path)Command:
pytestГаралт (сүүлийн мөр):
============================= 39 passed in 0.07s ==============================Бүх тест ногоон, шинэ харуул байрандаа. Таны тоо өөр байж болно.
Гинжилсэн алдаа
Заримдаа traceback нэг биш, хоёр байдаг. Энэ нь нэг алдааг барьж байхад өөр алдаа гарсан үед тохиолддог. Жишээ болгон үндсэн фолдерт chain_demo.py үүсгэнэ үү.
python
price = "хоёр мянга"
try:
int(price)
except ValueError:
raise ValueError(f"Bad price: {price!r}")Command:
python chain_demo.pyГаралт:
Traceback (most recent call last):
File "C:\Users\Bat\pytest-dadlaga\chain_demo.py", line 3, in <module>
int(price)
~~~^^^^^^^
ValueError: invalid literal for int() with base 10: 'хоёр мянга'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Bat\pytest-dadlaga\chain_demo.py", line 5, in <module>
raise ValueError(f"Bad price: {price!r}")
ValueError: Bad price: 'хоёр мянга'Хоёр traceback, тэдгээрийн хооронд холбогч өгүүлбэр. Доороос нь уншъя. Хамгийн доод traceback бол программыг зогсоосон алдаа: “Bad price: 'хоёр мянга'”, 5 дугаар мөрийн raise. Холбогч өгүүлбэр “During handling of the above exception, another exception occurred” нь "дээрх алдааг барьж байх үед өөр алдаа гарсан" гэсэн утгатай. Тэгэхээр дээд traceback бол анхны алдаа: int() "хоёр мянга" гэсэн текстийг тоо болгож чадаагүй. “invalid literal for int() with base 10” нь “int()-д аравтын системийн буруу бичиглэл” гэсэн утгатай.
Гинжилсэн traceback-ийг уншихдаа хоёуланг нь уншина: доод нь юу программыг зогсоосныг, дээд нь юунаас эхэлсэнийг хэлдэг. Ихэнхдээ жинхэнэ шалтгаан дээд, анхны алдаанд байдаг. Хэрвээ raise мөрийг raise ValueError(...) from err гэж, except-ийн алдааг except ValueError as err: хэлбэрээр барьж бичвэл холбогч өгүүлбэр “The above exception was the direct cause of the following exception” буюу "дээрх алдаа доорх алдааны шууд шалтгаан болсон" болж өөрчлөгдөнө. Энэ нь хоёр алдааны холбоо санаатай гэдгийг уншигчид хэлдэг. chain_demo.py-ийг устгана уу.
Сангийн дотуур дамжсан traceback
Traceback-ийн зарим давхар таны кодонд биш, Python-ий стандарт санд эсвэл суулгасан package-д байж болно. items.json-д санамсаргүй таслал нэмж үзье. Сүүний мөрийн араас таслал тавьж хадгална уу.
json
[
["талх", 2000, 2],
["сүү", 3000, 1],
]Command:
python report_app.pyГаралт:
Traceback (most recent call last):
File "C:\Users\Bat\pytest-dadlaga\report_app.py", line 4, in <module>
items = load_items("items.json")
File "C:\Users\Bat\pytest-dadlaga\storage.py", line 11, in load_items
items = [tuple(item) for item in json.load(f)]
~~~~~~~~~^^^
File "C:\Users\Bat\AppData\Local\Programs\Python\Python313\Lib\json\__init__.py", line 293, in load
return loads(fp.read(),
...
File "C:\Users\Bat\AppData\Local\Programs\Python\Python313\Lib\json\decoder.py", line 361, in raw_decode
obj, end = self.scan_once(s, idx)
~~~~~~~~~~~~~~^^^^^^^^
json.decoder.JSONDecodeError: Illegal trailing comma before end of array: line 4 column 18 (char 49)Энд “...” гэсэн хэсэгт хэдэн давхар товчилсон, таных бүтэн, урт байна. Дээд хоёр давхар таны файлууд. Үлдсэн давхрууд “Python313\Lib\json” гэсэн замтай: энэ бол Python-ий стандарт сангийн json модулийн дотоод файлууд. Тэдгээрийн кодыг та бичээгүй бөгөөд тэдгээрийг унших шаардлага бараг гардаггүй.
Ийм traceback-ийг унших дүрэм: хамгийн доод мөрийг уншаад, дараа нь өөрийн кодын хамгийн доод давхрыг ол. Хамгийн доод мөр “JSONDecodeError: Illegal trailing comma before end of array: line 4 column 18” нь “JSON задлахад алдаа: массивын төгсгөлийн өмнө хууль бус таслал, 4 дүгээр мөр, 18 дугаар багана” гэсэн утгатай. Энэ мессеж items.json-ийн яг тэр байрлалыг заадаг. Өөрийн кодын хамгийн доод давхар бол storage.py-ийн 11 дүгээр мөр, json.load(f) дуудлага: энд бид стандарт сан руу оров. Стандарт сангийн давхрууд зөвхөн json хэрхэн дотооддоо алдааг олсныг харуулна. Олон жил, олон сая хүн ашигласан тэр кодонд алдаа байх магадлал маш бага: 10.1 дүгээр хичээлийн "сангийн алдаа гэж таамаглах" анхааруулгыг санаарай. Тиймээс шалтгаан бараг үргэлж таны кодтой хиллэсэн газарт: энд таны өгсөн JSON файл. Python-ий хувилбараас хамаараад энэ мессеж “Expecting value” гэх мэт өөр хэлбэртэй байж болох ч мөр ба баганын дугаар байна.
items.json-оос илүү таслалыг устгаад хадгална уу.
Package-уудын traceback ч ижил: замд нь “venv\Lib\site-packages” гэсэн хэсэг байвал тэр нь pip-ээр суулгасан package. Дүрэм нь ижил: доод мөр, дараа нь өөрийн кодын хамгийн доод давхар.
pytest-ийн traceback
7.4 дүгээр хичээлд pytest-ийн уналтын блокийг уншсан. Олон давхар алдаа pytest-д гарахад тэр нь Python-ий traceback-тэй ижил бүтэцтэй боловч өөр хэлбэртэй: давхар бүр тасархай “_ _ _” шугамаар тусгаарлагдсан, “>” тэмдэг мөрийг заасан, давхар бүрийн эхэнд параметрүүдийн утгыг харуулсан, мөн давхар бүрийн төгсгөлд "файл:мөр" байршилтай. Унших дүрэм ижил: доороос эхэлж, давхар бүрт "энэ функц ямар утга хүлээн авсан бэ" гэж асууна. pytest-ийн параметрүүдийн утгыг харуулдаг онцлог мөрдөлтийг хурдасгадаг: “amount = ‘20002000’” гэсэн мөр Python-ий traceback-ийн бидний олон алхмаар хүрсэн дүгнэлтийг шууд харуулна.
Хүсвэл items.json-д өөр төрлийн алдаа оруулж, traceback бүрийг уншаад, дараа нь л шалтгааныг олоорой. Жишээ нь нэг барааны tuple-д гурвын оронд хоёр утга үлдээх, ["талх", 2000], эсвэл тоо ширхэгийг текст болгох, ["талх", 2000, “2”]. Хоёр дахь нь сонирхолтой: шинэ шалгалт үнийг шалгадаг ч тоо ширхэгийг шалгадаггүй. Traceback хаана дуусах, мессеж юу гэх, 2000 * "2" хэрхэн ажиллахыг урьдчилан таамаглаад, дараа нь ажиллуулж шалгаарай. Хүсвэл load_items-ийн шалгалтыг тоо ширхэгт ч өргөтгөж, тест нэмээрэй. Дууссаны дараа items.json-ийг зөв хэлбэрт нь буцаагаарай.
Зөвхөн дээрээс нь унших. Traceback-ийн эхний давхар ихэвчлэн таны script, бараг юу ч хэлэхгүй. Олон хүн эхний мөрийг уншаад “report_app.py-д алдаа байна” гэж дүгнэдэг. Гарчигт бичигдсэнчлэн “most recent call last”: хамгийн чухал мэдээлэл доор. Үргэлж хамгийн доод мөрөөс эхэл.
Алдаа гарсан мөрийг алдааны шалтгаан гэж үзэх. Хамгийн доод давхар алдаа илэрсэн газрыг заадаг, үүссэн газрыг биш. format_price-ийг "засаж" текст хүлээн авдаг болгох уруу таталт төрж магадгүй, жишээ нь int(amount) нэмэх. Энэ нь шинж тэмдгийг засах: “20002000” текстийг тоо болгоход 20 сая төгрөгийн баримт гарна. Давхар бүрт "энэ функц буруу ажилласан уу, эсвэл буруу утга хүлээн авсан уу" гэж асуу.
Traceback-д байхгүй функцийг мартах. Traceback зөвхөн идэвхтэй дуудлагуудыг харуулдаг. Буруу утга traceback-ийн дээд давхарт хүрсэн ч эх үүсвэр нь олдоогүй бол өгөгдлийн замаар үргэлжлүүл: тэр утгыг аль функц буцаасан, аль файлаас уншсан, аль хэрэглэгчийн оролтоос ирсэн? Шаардлагатай бол 10.2 дугаар хичээлийн debugger-ээр тэр функцийн буцаах мөчид зогсож, утгыг нь хар.
Мессежийн утгыг үл тоох. “Cannot specify ‘,’ with ‘s’” мессежийн “s” нь утгын төрлийг хэлж байсан. “got ‘2000’” мессежийн хашилт нь текст гэдгийг хэлж байсан. “line 4 column 18” нь файлын яг байрлалыг хэлж байсан. Мессежийн жижиг хэсэг бүр нотлох баримт. 10.1 дүгээр хичээлийн “3300 гэдэг тоо өөрөө юу вэ” гэсэн асуултын нэгэн адил "энэ мессежийн хэсэг бүр юу гэж байна вэ" гэж асуу.
Гинжилсэн traceback-ийн дээд хэсгийг алгасах. Хоёр traceback байх үед зөвхөн доодыг нь уншиж, “During handling...” өгүүлбэрийн дээрх анхны алдааг алгасах нь түгээмэл. Ихэнхдээ жинхэнэ шалтгаан дээд хэсэгт байдаг. Хоёуланг нь, холбогч өгүүлбэрийн хамт унш.
Сангийн давхарт удаан зогсох. json, pathlib зэрэг стандарт сангийн эсвэл package-ийн дотоод кодыг ойлгох гэж олон минут зарцуулах нь бараг үргэлж дэмий. Өөрийн кодын хамгийн доод давхрыг олоод, тэр мөрөнд сан руу юу дамжуулсныг шалга.
Traceback бол дуудлагын замын баримт: “most recent call last” буюу дээд давхар хамгийн эхний дуудлага, доод давхар алдаа гарах мөчийн дуудлага. Давхар бүр файлын зам, мөрийн дугаар, функцийн нэр, мөрийн кодыг агуулдаг бөгөөд “~” ба “^” тэмдэг мөрийн яг аль хэсгийг онож заадаг. Доороос эхэлж уншина: хамгийн доод мөр алдааны төрөл ба мессеж, тэр нь эхний нотлох баримт. Дараа нь давхар бүрт "энэ функц буруу ажилласан уу, эсвэл буруу утга хүлээн авсан уу" гэж асууж дээшилнэ. Алдаа илэрсэн газар ихэвчлэн үүссэн газар биш. Traceback зөвхөн идэвхтэй дуудлагуудыг харуулдаг тул аль хэдийн дуусч, буруу утгыг буцаасан функцууд түүнд байхгүй: дуудлагын замын дараа өгөгдлийн замыг мөшгөнө. Шалтгааныг эх үүсвэр дээр нь засаж, гадаад ертөнцөөс ирсэн өгөгдлийг ирмэг дээр нь шалгаснаар дараагийн алдаа үүссэн газартаа тодорхой мессежтэйгээр илэрнэ. Гинжилсэн traceback-ийн хоёуланг нь уншина, анхны шалтгаан ихэвчлэн дээд хэсэгт. Стандарт сан эсвэл package-ийн давхрууд байвал доод мөрийг уншаад, өөрийн кодын хамгийн доод давхрыг олно.
Дараагийн хичээлд print()-ийн нөгөө хязгаарыг, түр хэвлэлтүүдийг устгах, мартах асуудлыг шийднэ. Python-ий logging модуль бол програмыг хэвийн ажиллаж байх үед ч юу болж байгааг тэмдэглэдэг онгоцны хар хайрцаг юм. Түүний түвшнүүд, үндсэн тохиргоо, print-ээс яагаад ялгаатайг сурна.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.