Mẹo gỡ lỗi Python [đã đóng]


164

Lời khuyên tốt nhất của bạn để gỡ lỗi Python là gì?

Xin đừng liệt kê một trình gỡ lỗi cụ thể mà không nói những gì nó thực sự có thể làm.

Liên quan


Câu trả lời:


139

PDB

Bạn có thể sử dụng mô-đun pdb, chèn pdb.set_trace()bất cứ nơi nào và nó sẽ hoạt động như một điểm dừng.

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

Để tiếp tục thực hiện sử dụng c(hoặc conthoặc continue).

Có thể thực thi các biểu thức Python tùy ý bằng pdb. Ví dụ: nếu bạn tìm thấy một lỗi, bạn có thể sửa mã, sau đó nhập một biểu thức loại để có hiệu ứng tương tự trong mã đang chạy

ipdb là phiên bản của pdb cho IPython . Nó cho phép sử dụng pdb với tất cả các tính năng IPython bao gồm hoàn thành tab.

Cũng có thể đặt pdb để tự động chạy trên một ngoại lệ chưa được lưu.

Pydb được viết là phiên bản nâng cao của Pdb. Những lợi ích?


Đây là một bài viết về việc sử dụng pdb: sontek.net/debugging-python-with-pdb
sontek

Cá nhân, tôi thích ipdb hơn.
Sardathrion - chống lại lạm dụng SE

1
Rõ ràng có một bản viết lại của pydb được gọi là pydbgr
Ehtesh Choudhury

SublimeText có một plugin tuyệt vời để thêm các điểm dừng python vào mã: sublime.wbond.net/packages/Python%20Breakpoint
Dennis Golomazov

Nếu bạn đang phát triển một ứng dụng web, hãy thêm chế độ xem myserver.com/pdbtrong chế độ gỡ lỗi đơn giản import pdb; pdb.set_trace(). Nếu bạn đang sử dụng Flask / Werkzeug có trình gỡ lỗi tương tác, bạn cũng có thể có một chế độ xem assert False.
osa

78

http://pypi.python.org/pypi/pudb , trình gỡ lỗi Python toàn màn hình, dựa trên bảng điều khiển.

Mục tiêu của nó là cung cấp tất cả các tính năng của trình gỡ lỗi dựa trên GUI hiện đại trong một gói thân thiện với bàn phím và nhẹ hơn. PuDB cho phép bạn gỡ lỗi mã ngay tại nơi bạn viết và kiểm tra nó - trong một thiết bị đầu cuối. Nếu bạn đã làm việc với các công cụ Turbo Pascal hoặc C dựa trên DOS xuất sắc (nhưng ngày nay), giao diện người dùng của PuDB có thể trông quen thuộc.

ảnh chụp màn hình pudb

Rất vui để gỡ lỗi các tập lệnh độc lập, chỉ cần chạy

python -m pudb.run my-script.py

Cài đặt vớipip install pudb
congusbongus

40

Nếu bạn đang sử dụng pdb, bạn có thể xác định bí danh cho các phím tắt. Tôi sử dụng những thứ này:

# 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

Làm thế nào để bạn xác định những bí danh?
Casebash

9
Đặt công cụ này vào ~ / .pdbrc
Ned Batchelder

trên các cửa sổ, bạn có thể đặt nó vào ~ / _ipython / ipythonrc.ini
fastmultiplication

33

Ghi nhật ký

Python đã có một mô-đun đăng nhập tích hợp tuyệt vời . Bạn có thể muốn sử dụng mẫu đăng nhập ở đây .

Mô-đun đăng nhập cho phép bạn xác định mức độ quan trọng; trong quá trình gỡ lỗi, bạn có thể ghi nhật ký mọi thứ, trong khi hoạt động bình thường, bạn chỉ có thể ghi nhật ký những điều quan trọng. Bạn có thể tắt và bật mọi thứ.

Hầu hết mọi người chỉ sử dụng các câu lệnh in cơ bản để gỡ lỗi, và sau đó loại bỏ các câu lệnh in. Tốt hơn là để chúng vào, nhưng vô hiệu hóa chúng; sau đó, khi bạn gặp một lỗi khác, bạn có thể kích hoạt lại mọi thứ và xem nhật ký của mình.

Đây có thể là cách tốt nhất có thể để gỡ lỗi các chương trình cần thực hiện nhanh chóng, chẳng hạn như các chương trình mạng cần phản hồi trước khi đầu kia của kết nối mạng hết thời gian và biến mất. Bạn có thể không có nhiều thời gian để một bước gỡ lỗi; nhưng bạn chỉ có thể để mã của mình chạy và ghi nhật ký mọi thứ, sau đó xem qua nhật ký và tìm hiểu điều gì đang thực sự xảy ra.

EDIT: URL ban đầu cho các mẫu là: http://aymanh.com/python-debugging-t kỹ thuật

Trang này bị thiếu nên tôi đã thay thế nó bằng một tham chiếu đến ảnh chụp nhanh được lưu trữ tại archive.org: http://web.archive.org/web/20120819135307/http://aymanh.com/python-debugging-t kỹ thuật

Trong trường hợp nó biến mất một lần nữa, đây là các mẫu tôi đã đề cập. Đây là mã được lấy từ blog; Tôi đã không viết nó.

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()

Và đây là lời giải thích của ông về cách sử dụng ở trên. Một lần nữa, tôi không nhận được tín dụng cho việc này:


Theo mặc định, mô-đun đăng nhập in các thông báo quan trọng, lỗi và cảnh báo. Để thay đổi điều này sao cho tất cả các cấp được in, hãy sử dụng:

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

Để gửi thông điệp tường trình đến một tệp có tên debug.log, hãy sử dụng:

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


1
Vấn đề với mô-đun ghi nhật ký là nó bị hỏng rất nhiều với Unicode và các cách giải quyết khác nhau là cần thiết để nó hoạt động trong một ứng dụng quốc tế. Mặc dù vậy, đây vẫn là giải pháp ghi nhật ký tốt nhất cho Python.
Jacek Konieczny

Liên kết "đăng nhập mẫu ở đây" đã chết. Vui lòng cập nhật.
Yohann

20

Có thể in những dòng Python được thực thi (cảm ơn Geo!). Điều này có bất kỳ số lượng ứng dụng nào, ví dụ, bạn có thể sửa đổi nó để kiểm tra khi các chức năng cụ thể được gọi hoặc thêm một cái gì đó như ## làm cho nó chỉ theo dõi các dòng cụ thể.

code.interact đưa bạn vào một bảng điều khiển tương tác

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

Nếu bạn muốn có thể dễ dàng truy cập vào lịch sử bảng điều khiển của mình, hãy xem: " Tôi có thể có một cơ chế lịch sử như trong vỏ không? " (Sẽ phải xem thường nó).

Tự động hoàn thành có thể được kích hoạt cho trình thông dịch .


19

ipdb giống như pdb, với sự tuyệt vời của ipython.


5
Bạn có thể thêm chi tiết về những gì nó có thể làm?
Casebash

17

print các câu lệnh

  • Một số người đề xuất một debug_printchức năng thay vì in để dễ dàng vô hiệu hóa
  • Các pprintmô-đun là vô giá cho các cấu trúc phức tạp

3
+1 khi mọi trình gỡ lỗi không thành công, in là bạn của bạn, vâng debug_print sẽ là sự bổ sung tuyệt vời
Anurag Uniyal

Tôi thường in đầu tiên sau đó gỡ lỗi thứ hai trừ khi tôi biết tôi sẽ có thể giải quyết bằng cách truy tìm một phần cụ thể
Casebash

4
Trên thực tế mô-đun đăng nhập làm điều đó.
e-satis

Đúng, nhưng đăng nhập phải được thiết lập. Tôi sẽ học cách sử dụng mô-đun sau khi được vinh danh
Casebash

in có thể hữu ích cho các trường hợp đơn giản và đặc biệt là khi phát triển các dự án với thời gian khởi động nhỏ. Mặt khác, nó có thể gây nghiện và sử dụng nó trên pdb hoặc bất kỳ trình gỡ lỗi nào khác trong các tình huống phức tạp hơn thường sẽ khiến bạn đau đầu
vinilios

16

cách rõ ràng để gỡ lỗi một kịch bản

python -m pdb script.py
  • hữu ích khi tập lệnh đó đưa ra một ngoại lệ
  • hữu ích khi sử dụng lệnh virtualenv và pdb không chạy với phiên bản python venvs.

nếu bạn không biết chính xác kịch bản đó ở đâu

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

15

PyDev

PyDev có một trình gỡ lỗi tương tác khá tốt. Nó có biểu thức đồng hồ, di chuột để đánh giá, danh sách chủ đề và ngăn xếp và (gần như) tất cả các tiện nghi thông thường mà bạn mong đợi từ trình gỡ lỗi trực quan hiện đại. Bạn thậm chí có thể đính kèm vào một quy trình đang chạy và thực hiện sửa lỗi từ xa.

Tuy nhiên, giống như các trình gỡ lỗi trực quan khác, tôi thấy nó hữu ích cho các vấn đề đơn giản hoặc cho các vấn đề rất phức tạp sau khi tôi đã thử mọi thứ khác. Tôi vẫn làm hầu hết các công việc nặng với đăng nhập.


Liệu nó có khả năng chỉnh sửa và tiếp tục?
Casebash

@CaseBash không, nhưng tính năng này đã được lên kế hoạch. Ngay cả khi không có nó, tốc độ và dễ dàng thiết lập / bỏ đặt các điểm dừng và xem qua các giá trị biến vẫn rất hữu ích
Jiaaro


12

Winpdb rất đẹp và trái với tên gọi của nó, nó hoàn toàn đa nền tảng.

Nó có một trình gỡ lỗi GUI dựa trên dấu nhắc rất đẹp và hỗ trợ gỡ lỗi từ xa.


@Casebash - thêm chi tiết
orip

1
+1 Đây là trình gỡ lỗi python duy nhất mà tôi đã tìm thấy cho đến nay có thể xử lý đa luồng.
Lee Netherton

Hãy cẩn thận với "xử lý" đa luồng của nó - bất kỳ ngoại lệ nào trong bất kỳ luồng nào đều khiến toàn bộ quá trình bị đóng băng. Không phải là một điều xấu nếu bạn nhận thức được nó, rất đau đớn nếu bạn không
Walt W

Dự án có vẻ đã chết vào tháng 4 năm 2014
Alojz Janez

7

Trong Vim, tôi có ba ràng buộc sau:

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>

rpdb2là một trình gỡ lỗi Python từ xa, có thể được sử dụng với WinPDB, một trình gỡ lỗi đồ họa vững chắc. Bởi vì tôi biết bạn sẽ yêu cầu, nó có thể làm mọi thứ mà tôi mong đợi một trình gỡ lỗi đồ họa sẽ làm :)

Tôi sử dụng pdbtừ nose.toolsđó để tôi có thể gỡ lỗi các bài kiểm tra đơn vị cũng như mã thông thường.

Cuối cùng, F7ánh xạ sẽ in một dấu vết (tương tự như loại bạn nhận được khi có một ngoại lệ bong bóng trên đỉnh của ngăn xếp). Tôi đã tìm thấy nó thực sự hữu ích hơn một vài lần.


4

Xác định repr hữu ích các phương thức () cho các lớp của bạn (để bạn có thể thấy đối tượng là gì) và sử dụng định dạng repr () hoặc "% r"% (...) hoặc "... {0! R} ..". (...) trong các thông báo / nhật ký gỡ lỗi của bạn là IMHO một chìa khóa để gỡ lỗi hiệu quả.

Ngoài ra, các trình gỡ lỗi được đề cập trong các câu trả lời khác sẽ sử dụng các phương thức repr ().


2

Nhận một dấu vết ngăn xếp từ một ứng dụng Python đang chạy

Có một số thủ thuật ở đây . Bao gồm các

  • Đột nhập vào trình thông dịch / in dấu vết ngăn xếp bằng cách gửi tín hiệu
  • Lấy dấu vết ngăn xếp ra khỏi quy trình Python chưa chuẩn bị
  • Chạy trình thông dịch với các cờ để làm cho nó hữu ích để gỡ lỗi

2

Nếu bạn không thích dành thời gian cho trình gỡ lỗi (và không đánh giá cao khả năng sử dụng kém của pdbgiao diện dòng lệnh), bạn có thể bỏ dấu vết thực thi và phân tích nó sau. Ví dụ:

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

Điều này sẽ kết xuất tất cả các dòng setup.py installthực thi nguồn execution.log.

Để dễ dàng tùy chỉnh đầu ra theo dõi và viết các bộ theo dõi của riêng bạn, tôi kết hợp một số đoạn mã vào mô-đun xtrace (miền công cộng).


1

Khi có thể, tôi gỡ lỗi bằng cách sử dụng M-x pdbtrong emacs để gỡ lỗi ở mức nguồn.


1

Có một khóa học trực tuyến đầy đủ có tên là " Gỡ lỗi phần mềm " của Andreas Zeller trên Udacity, được đóng gói với các mẹo về gỡ lỗi:

Tóm tắt Khóa học

Trong lớp này, bạn sẽ học cách gỡ lỗi chương trình một cách có hệ thống, cách tự động hóa quá trình gỡ lỗi và xây dựng một số công cụ gỡ lỗi tự động trong Python.

Tại sao nên tham gia khóa học này?

Kết thúc khóa học này, bạn sẽ có một sự hiểu biết vững chắc về gỡ lỗi hệ thống, sẽ biết cách tự động gỡ lỗi và sẽ xây dựng một số công cụ gỡ lỗi chức năng trong Python.

Điều kiện tiên quyết và yêu cầu

Cần có kiến ​​thức cơ bản về lập trình và Python ở cấp độ Udacity CS101 hoặc tốt hơn. Hiểu biết cơ bản về lập trình hướng đối tượng là hữu ích.

Rất khuyến khích.


0

nếu bạn muốn có một cách đồ họa đẹp để in ngăn xếp cuộc gọi của mình theo cách dễ đọc, hãy xem tiện ích này: https://github.com/joerick/pyinstrument

Chạy từ dòng lệnh:

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

Chạy như một mô-đun:

from pyinstrument import Profiler

profiler = Profiler()
profiler.start()

# code you want to profile

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

Chạy với django:

Chỉ cần thêm pyinstrument.middleware.ProfilerMiddlewarevào MIDDLEWARE_CLASSES, sau đó thêm ?profilevào cuối URL yêu cầu để kích hoạt trình hồ sơ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.