เคล็ดลับการดีบัก Python [ปิด]


164

อะไรคือเคล็ดลับที่ดีที่สุดในการดีบัก Python

โปรดอย่าเพิ่งระบุบั๊กที่เฉพาะเจาะจงโดยไม่บอกว่ามันสามารถทำอะไรได้บ้าง

ที่เกี่ยวข้อง


คำตอบ:


139

PDB

คุณสามารถใช้โมดูล pdb แทรกpdb.set_trace()ได้ทุกที่และจะทำหน้าที่เป็นเบรกพอยต์

>>> import pdb
>>> a="a string"
>>> pdb.set_trace()
--Return--
> <stdin>(1)<module>()->None
(Pdb) p a
'a string'
(Pdb)

หากต้องการใช้งานการดำเนินการต่อc(หรือcontหรือcontinue)

มีความเป็นไปได้ที่จะใช้งาน Python โดยใช้ pdb ตัวอย่างเช่นหากคุณพบข้อผิดพลาดคุณสามารถแก้ไขรหัสแล้วพิมพ์นิพจน์ประเภทเพื่อให้มีผลเหมือนกันในรหัสที่ทำงาน

ipdb เป็นรุ่นของ PDB สำหรับIPython อนุญาตให้ใช้ pdb พร้อมกับคุณสมบัติ IPython ทั้งหมดรวมถึงการทำให้แท็บสมบูรณ์

นอกจากนี้ยังเป็นไปได้ที่จะตั้งค่า pdb ให้ทำงานโดยอัตโนมัติในข้อยกเว้นที่ไม่ได้ตรวจสอบ

Pydbถูกเขียนเป็นPdbรุ่นปรับปรุง ประโยชน์ที่ได้รับ?


นี่คือบทความเกี่ยวกับการใช้ pdb: sontek.net/debugging-python-with-pdb
sontek

โดยส่วนตัวแล้วฉันชอบipdbดีกว่า
Sardathrion - ต่อต้านการล่วงละเมิดทาง SE

1
เห็นได้ชัดว่ามีการเขียนซ้ำของ pydb เรียกว่าpydbgr
Ehtesh Choudhury

SublimeText มีปลั๊กอินที่ยอดเยี่ยมในการเพิ่มจุดพักหลามในโค้ด: sublime.wbond.net/packages/Python%20Breakpoints
Dennis Golomazov

หากคุณมีการพัฒนาโปรแกรมประยุกต์บนเว็บ, เพิ่มมุมมองสำหรับในโหมดการแก้ปัญหาที่ไม่เพียงmyserver.com/pdb import pdb; pdb.set_trace()หากคุณกำลังใช้ขวด / Werkzeug assert Falseที่มีการดีบักโต้ตอบคุณยังสามารถมีมุมมองที่ไม่เพียง
osa

78

http://pypi.python.org/pypi/pudbตัวดีบัก Python แบบเต็มหน้าจอ

เป้าหมายของเราคือการให้บริการดีบั๊กอันทันสมัยบนพื้นฐานของ GUI ในแพ็คเกจที่มีน้ำหนักเบากว่าและเป็นมิตรกับคีย์บอร์ด PuDB ช่วยให้คุณสามารถดีบักรหัสได้ทันทีเมื่อคุณเขียนและทดสอบ - ในเทอร์มินัล หากคุณเคยทำงานกับเครื่องมือ Pascal หรือ C ที่เป็น Turbo (ยอดเยี่ยมในสมัยโบราณ), UI ของ PuDB อาจดูคุ้นเคย

ภาพหน้าจอ pudb

ดีสำหรับการดีบักสคริปต์แบบสแตนด์อโลนเพียงรัน

python -m pudb.run my-script.py

ติดตั้งด้วยpip install pudb
congusbongus

40

หากคุณใช้ pdb คุณสามารถกำหนดชื่อแทนสำหรับทางลัด ฉันใช้สิ่งเหล่านี้:

# Ned's .pdbrc

# Print a dictionary, sorted. %1 is the dict, %2 is the prefix for the names.
alias p_ for k in sorted(%1.keys()): print "%s%-15s= %-80.80s" % ("%2",k,repr(%1[k]))

# Print the instance variables of a thing.
alias pi p_ %1.__dict__ %1.

# Print the instance variables of self.
alias ps pi self

# Print the locals.
alias pl p_ locals() local:

# Next and list, and step and list.
alias nl n;;l
alias sl s;;l

# Short cuts for walking up and down the stack
alias uu u;;u
alias uuu u;;u;;u
alias uuuu u;;u;;u;;u
alias uuuuu u;;u;;u;;u;;u
alias dd d;;d
alias ddd d;;d;;d
alias dddd d;;d;;d;;d
alias ddddd d;;d;;d;;d;;d

คุณจะกำหนดนามแฝงเหล่านี้ได้อย่างไร
Casebash

9
ใส่สิ่งนี้ใน ~ / .pdbrc
Ned Batchelder

บน windows คุณสามารถใส่ไว้ใน ~ / _ipython / ipythonrc.ini
fastmultiplication

33

เข้าสู่ระบบ

Python มีโมดูลการบันทึกในตัวที่ยอดเยี่ยมอยู่แล้ว คุณอาจต้องการที่จะใช้แม่แบบการเข้าสู่ระบบที่นี่

โมดูลการบันทึกช่วยให้คุณระบุระดับความสำคัญได้ ในระหว่างการดีบักคุณสามารถบันทึกทุกอย่างในขณะที่ในระหว่างการทำงานปกติคุณอาจบันทึกสิ่งที่สำคัญเท่านั้น คุณสามารถปิดและเปิดสิ่งต่างๆ

คนส่วนใหญ่ใช้คำสั่งการพิมพ์พื้นฐานเพื่อดีบักแล้วลบคำสั่งการพิมพ์ เป็นการดีกว่าที่จะปล่อยไว้ แต่ปิดการใช้งาน จากนั้นเมื่อคุณมีข้อผิดพลาดอื่นคุณสามารถเปิดใช้งานทุกอย่างอีกครั้งและดูบันทึกของคุณ

นี่อาจเป็นวิธีที่ดีที่สุดในการดีบักโปรแกรมที่ต้องทำสิ่งต่าง ๆ อย่างรวดเร็วเช่นโปรแกรมเครือข่ายที่ต้องตอบสนองก่อนที่ปลายอีกด้านหนึ่งของการเชื่อมต่อเครือข่ายจะหมดเวลาและหายไป คุณอาจไม่มีเวลามากในการดีบักเกอร์แบบขั้นตอนเดียว แต่คุณสามารถปล่อยให้โค้ดของคุณทำงานและบันทึกทุกอย่างจากนั้นจึงทำการเจาะรูล็อกและหาว่าเกิดอะไรขึ้นจริง ๆ

แก้ไข: URL ดั้งเดิมสำหรับเทมเพลตคือ: http://aymanh.com/python-debugging-techniques

หน้านี้หายไปดังนั้นฉันจึงแทนที่ด้วยการอ้างอิงถึงสแนปชอตที่บันทึกไว้ที่ archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-techniques

ในกรณีที่มันหายไปอีกครั้งนี่คือเทมเพลตที่ฉันพูดถึง นี่คือรหัสที่นำมาจากบล็อก ฉันไม่ได้เขียนมัน

import logging
import optparse

LOGGING_LEVELS = {'critical': logging.CRITICAL,
                  'error': logging.ERROR,
                  'warning': logging.WARNING,
                  'info': logging.INFO,
                  'debug': logging.DEBUG}

def main():
  parser = optparse.OptionParser()
  parser.add_option('-l', '--logging-level', help='Logging level')
  parser.add_option('-f', '--logging-file', help='Logging file name')
  (options, args) = parser.parse_args()
  logging_level = LOGGING_LEVELS.get(options.logging_level, logging.NOTSET)
  logging.basicConfig(level=logging_level, filename=options.logging_file,
                      format='%(asctime)s %(levelname)s: %(message)s',
                      datefmt='%Y-%m-%d %H:%M:%S')

  # Your program goes here.
  # You can access command-line arguments using the args variable.

if __name__ == '__main__':
  main()

และนี่คือคำอธิบายของเขาเกี่ยวกับวิธีการใช้ข้างต้น อีกครั้งฉันไม่ได้รับเครดิตสำหรับสิ่งนี้:


โดยค่าเริ่มต้นโมดูลการบันทึกจะพิมพ์ข้อความวิกฤติข้อผิดพลาดและคำเตือน หากต้องการเปลี่ยนแปลงสิ่งนี้เพื่อให้พิมพ์ทุกระดับให้ใช้:

$ ./your-program.py --logging=debug

ในการส่งข้อความบันทึกไปยังไฟล์ชื่อ debug.log ใช้:

$ ./your-program.py --logging-level=debug --logging-file=debug.log


1
ปัญหาเกี่ยวกับการบันทึกโมดูลคือมันทำลายอย่างมากกับ Unicode และการแก้ปัญหาต่าง ๆ ที่จำเป็นเพื่อให้มันทำงานภายในแอปพลิเคชันสากล แม้ว่านี่จะเป็นวิธีการบันทึกที่ดีที่สุดสำหรับ Python
Jacek Konieczny

ลิงก์ "เทมเพลตการบันทึกที่นี่" ลิงก์ตาย โปรดอัปเดต
โยฮันน์

20

เป็นไปได้ที่จะพิมพ์สิ่งที่บรรทัด Python จะดำเนินการ (ขอบคุณ Geo!) ตัวอย่างนี้มีแอปพลิเคชันจำนวนมากเช่นคุณสามารถปรับเปลี่ยนเพื่อตรวจสอบเมื่อมีการเรียกใช้ฟังก์ชั่นเฉพาะหรือเพิ่มบางอย่างเช่น ## ทำให้มันติดตามเฉพาะบางบรรทัด

code.interact จะนำคุณเข้าสู่คอนโซลแบบโต้ตอบ

import code; code.interact(local=locals())

หากคุณต้องการเข้าถึงประวัติคอนโซลของคุณอย่างง่ายดาย: " ฉันมีกลไกประวัติเหมือนในเชลล์ได้หรือไม่? " (จะต้องดูมันก่อน)

อัตโนมัติสมบูรณ์สามารถเปิดใช้งานสำหรับล่าม


19

ipdb เป็นเหมือน pdb โดยมีความเป็นสุดยอดของ ipython


5
คุณช่วยเพิ่มรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่สามารถทำได้หรือไม่?
Casebash

17

print งบ

  • บางคนแนะนำdebug_printฟังก์ชั่นแทนการพิมพ์เพื่อให้ง่ายต่อการปิดการใช้งาน
  • pprintโมดูลเป็นสิ่งล้ำค่าสำหรับโครงสร้างที่ซับซ้อน

3
+1 เมื่อดีบักเกอร์ทุกตัวล้มเหลวการพิมพ์คือเพื่อนของคุณใช่ debug_print น่าจะเป็นสิ่งที่ดียิ่งกว่านี้
Anurag Uniyal

ฉันมักพิมพ์ครั้งแรกแล้วการแก้ปัญหาที่สองยกเว้นเมื่อผมรู้ว่าผมจะสามารถที่จะแก้ปัญหาโดยการติดตามส่วนหนึ่ง
Casebash

4
อันที่จริงโมดูลบันทึกทำเช่นนั้น
e-Satisfaction

จริง แต่ต้องมีการตั้งค่าการบันทึก ฉันจะเรียนรู้วิธีใช้งานโมดูลหลังจากได้รับเกียรตินิยม
Casebash

การพิมพ์จะมีประโยชน์สำหรับกรณีง่าย ๆ และโดยเฉพาะอย่างยิ่งเมื่อพัฒนาโครงการที่มีเวลาเริ่มต้นเพียงเล็กน้อย ในอีกด้านหนึ่งก็สามารถเสพติดและใช้งานได้มากกว่า pdb หรือดีบักเกอร์อื่น ๆ ในสถานการณ์ที่ซับซ้อนมากขึ้นมักจะทำให้คุณปวดหัว
vinilios

16

วิธีที่ชัดเจนในการดีบักสคริปต์

python -m pdb script.py
  • มีประโยชน์เมื่อสคริปต์นั้นทำให้เกิดข้อยกเว้น
  • มีประโยชน์เมื่อใช้คำสั่ง virtualenv และ pdb ไม่ได้ทำงานกับรุ่น python venvs

หากคุณไม่ทราบว่าสคริปต์นั้นอยู่ตรงไหน

python -m pdb ``which <python-script-name>``

15

PyDev

PyDevมีบั๊กอินเทอร์แอคทีฟที่ดีพอสมควร มีการแสดงรายการการเลื่อนไปยังการประเมินเธรดและสแต็กและ (เกือบ) สิ่งอำนวยความสะดวกตามปกติที่คุณคาดหวังจากดีบักเกอร์ภาพที่ทันสมัย คุณสามารถแนบกับกระบวนการทำงานและทำการดีบักแบบรีโมทได้

เช่นเดียวกับนักแก้จุดบกพร่องทางสายตาอื่น ๆ ฉันพบว่ามันมีประโยชน์ส่วนใหญ่สำหรับปัญหาง่าย ๆ หรือสำหรับปัญหาที่ซับซ้อนมากหลังจากที่ฉันลองทุกอย่างอื่นแล้ว ฉันยังคงทำการยกส่วนใหญ่อย่างหนักด้วยการบันทึก


มีความสามารถในการแก้ไขและดำเนินการต่อหรือไม่
Casebash

@CaseBash ไม่ได้ทำ แต่มีการวางแผนคุณสมบัติ แม้ว่าจะไม่มีมันแล้วความเร็วและความง่ายในการตั้งค่า / ยกเลิกการตั้งค่าเบรกพอยต์และการดูค่าตัวแปรยังคงมีประโยชน์มาก
Jiaaro


12

Winpdbเป็นคนดีมากและตรงกันข้ามกับชื่อของมันมันเป็นแพลตฟอร์มข้ามสมบูรณ์

มันมีดีบอมต์อิงและดีบั๊กดีบั๊กและสนับสนุนการดีบักแบบรีโมท


@Casebash - เพิ่มรายละเอียดเพิ่มเติม
orip

1
+1 นี่คือดีบักหลามเดียวที่ฉันพบจนถึงตอนนี้ที่สามารถจัดการเธรดหลายเธรดได้
Lee Netherton

ระวังด้วย "การจัดการ" การมัลติเธรด - ข้อยกเว้นใด ๆ ในเธรดทำให้กระบวนการทั้งหมดหยุดทำงาน ไม่ใช่เรื่องเลวร้ายหากคุณตระหนักถึงมันเจ็บปวดมากถ้าคุณไม่
Walt W

โครงการดูจะตายเมื่อเมษายน 2014
Alojz Janez

7

ในกลุ่มฉันมีสามสิ่งที่ผูกไว้:

map <F9> Oimport rpdb2; rpdb2.start_embedded_debugger("asdf") #BREAK<esc>
map <F8> Ofrom nose.tools import set_trace; set_trace() #BREAK<esc>
map <F7> Oimport traceback, sys; traceback.print_exception(*sys.exc_info()) #TRACEBACK<esc>

rpdb2เป็น Remote Python Debugger ซึ่งสามารถใช้กับ WinPDB ซึ่งเป็น debugger แบบกราฟิกที่แข็งแกร่ง เพราะฉันรู้ว่าคุณจะถามมันก็สามารถทำทุกอย่างที่ฉันคาดหวังให้ดีบักเกอร์กราฟิกทำ :)

ผมใช้pdbจากnose.toolsเพื่อที่จะสามารถแก้ปัญหาการทดสอบหน่วยเช่นเดียวกับรหัสปกติ

ในที่สุดการF7ทำแผนที่จะพิมพ์การติดตามย้อนกลับ (คล้ายกับชนิดที่คุณได้รับเมื่อมีข้อยกเว้นฟองอากาศที่ด้านบนของสแต็ก) ฉันพบว่ามันมีประโยชน์มากกว่าสองสามครั้ง


4

การกำหนดเมธอดrepr () ที่มีประโยชน์สำหรับคลาสของคุณ (เพื่อให้คุณสามารถดูว่าวัตถุคืออะไร) และใช้ repr () หรือ "% r"% (... ) หรือ "... {0! r} .. " (... ) ในข้อความ / บันทึกการดีบักของคุณคือ IMHO ซึ่งเป็นกุญแจสำคัญในการแก้ไขข้อบกพร่องอย่างมีประสิทธิภาพ

นอกจากนี้ตัวดีบั๊กที่กล่าวถึงในคำตอบอื่น ๆ จะใช้ประโยชน์จากวิธีการrepr ()


2

รับการติดตามสแต็กจากแอ็พพลิเคชัน Python ที่รันอยู่

มีหลายเทคนิคอยู่ที่นี่ เหล่านี้ ได้แก่

  • แบ่งเป็นล่าม / พิมพ์กองติดตามโดยการส่งสัญญาณ
  • รับการติดตามสแต็กจากกระบวนการ Python ที่ไม่ได้เตรียมตัวไว้
  • เรียกใช้ล่ามด้วยแฟล็กเพื่อให้มีประโยชน์สำหรับการดีบัก

2

หากคุณไม่ชอบใช้เวลากับ debuggers (และไม่เห็นคุณค่าการใช้งานที่ไม่ดีของpdbอินเตอร์เฟสบรรทัดคำสั่ง) คุณสามารถดัมพ์การติดตามการเรียกใช้งานและวิเคราะห์ในภายหลัง ตัวอย่างเช่น:

python -m trace -t setup.py install > execution.log

นี้จะถ่ายโอนสายทุกแหล่งที่มาของการดำเนินการsetup.py installexecution.log

เพื่อให้ง่ายต่อการปรับแต่งผลลัพธ์การติดตามและเขียนตัวติดตามของคุณเองฉันได้รวบรวมโค้ดบางส่วนไว้ในโมดูลxtrace (โดเมนสาธารณะ)


1

เมื่อเป็นไปได้ฉันจะใช้ debug M-x pdbใน emacs เพื่อทำการดีบั๊กระดับซอร์ส


1

มีหลักสูตรออนไลน์เต็มรูปแบบที่เรียกว่า " การแก้จุดบกพร่องซอฟต์แวร์ " โดย Andreas Zeller บน Udacity เต็มไปด้วยเคล็ดลับเกี่ยวกับการดีบัก:

สรุปหลักสูตร

ในคลาสนี้คุณจะได้เรียนรู้วิธีการดีบักโปรแกรมอย่างเป็นระบบ, วิธีการทำให้กระบวนการดีบั๊กโดยอัตโนมัติและสร้างเครื่องมือการดีบั๊กแบบอัตโนมัติใน Python

ทำไมต้องเรียนหลักสูตรนี้

ในตอนท้ายของหลักสูตรนี้คุณจะมีความเข้าใจที่ดีเกี่ยวกับการดีบักอย่างเป็นระบบจะรู้วิธีการดีบักอัตโนมัติและจะสร้างเครื่องมือการดีบักที่ใช้งานได้หลายอย่างใน Python

ข้อกำหนดเบื้องต้นและข้อกำหนด

ต้องมีความรู้พื้นฐานเกี่ยวกับการเขียนโปรแกรมและ Python ในระดับ Udacity CS101 ขึ้นไป ความเข้าใจพื้นฐานของการเขียนโปรแกรมเชิงวัตถุนั้นมีประโยชน์

แนะนำเป็นอย่างยิ่ง


0

หากคุณต้องการวิธีที่ดีในการพิมพ์สแต็คการโทรของคุณในแบบที่อ่านได้ตรวจสอบยูทิลิตี้นี้: https://github.com/joerick/pyinstrument

เรียกใช้จากบรรทัดคำสั่ง:

python -m pyinstrument myscript.py [args...]

ทำงานเป็นโมดูล:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

profiler.stop()
print(profiler.output_text(unicode=True, color=True))

ทำงานกับ django:

เพียงแค่เพิ่มpyinstrument.middleware.ProfilerMiddlewareไปMIDDLEWARE_CLASSESแล้วเพิ่ม?profileต่อท้าย URL คำขอเพื่อเปิดใช้งานรวมข้อมูล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.