> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
4Giới thiệu
Gỡ lỗi [Debugging] là một trong những điều kinh khủng, khó ưa nhất trong phát triển phần mềm, nhưng điều ngang trái thay nó lại là một trong những thứ quan trọng bậc nhất trong vòng đời phát triển phần mềm. Chắc chắn trong giai đoạn phát triển, mọi lập trình viên đều phải tự debug mã của mình, điều này là không thể tránh khỏi.
Có rất nhiều cách để debug một ứng dụng viết ra. Một phương pháp được sử dụng rất phổ biến đó là sử dụng câu lệnh "print" trong các trường hợp để xem nó chạy như thế nào trong khi thực thi chương trình. Tuy nhiên, phương pháp này xảy ra nhiều vấn đề, chẳng hạn như việc muốn in được các giá trị của biến thì phải thêm code vào, v.v.. => Quá phức tạp. Hơn nữa cách này chỉ dùng tạm bợ cho những chương trình nhỏ, tầm trăm dòng code trở lại thì ok, khi mà sang một chương trình lớn hơn, có nhiều file hơn, thì nó lại là một vấn đề lớn lớn lớn.
Vậy thì, chúng ta đã có trình gỡ lỗi để giải quyết vấn đề đó cho. Nó giúp chúng ta tìm các lỗi trong một ứng dụng bằng các lệnh bên ngoài, do đó không có thay đổi nào đối với code. Như đã đề cập ở trên, mình muốn giới thiệu các bạn module PDB - một module tích hợp bên trong python [không cần phải cài đặt từ nguồn bên ngoài], thông qua bài viết "Có PDB, debug python không còn khó khăn".
Mời các bạn đọc tiếp.
Các lệnh thao tác cơ bản
Để hiểu các lệnh hoặc công cụ chính có trong PDB, mình sẽ viết một đoạn chương trình nho nhỏ, vui vui, cơ bản, sau đó thử debug bằng các lệnh PDB. Bằng các này, chúng ta sẽ thấy được một cách rõ ràng hơn, chính xác hơn mỗi lệnh của PDB sẽ làm gì.
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
5list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
love_codes = [1111112, 2111014, 3451524, 4512244]
def show_list_crush[]:
print['List crush: ']
for crush in list_crush:
print[crush]
print["Code of loves: "]
for code in love_codes:
print[code]
def main[]:
show_list_crush[]
if __name__ == "__main__":
main[]
Kết quả của đoạn script trên:
List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
Đoạn mã trên chắc mình cũng không cần phải giải thích nhiều, vì nó là basic đối với một người làm về python rồi, nó không có gì khó cũng như cú pháp phức tạp cả. Bạn không cần phải hiểu đoạn lệnh trên thực hiện, mục đích chính của mình thực hiện một số lệnh PDB dựa trên chương trình này. Ok, bắt đầu thôi.
Sử dụng PDB yêu cầu sử dụng Command Line Interface [CLI], do đó bạn phải chạy ứng dụng của mình từ
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
6 hoặc > /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
7.Chạy lệnh dưới đây trong CLI của bạn:
python -m pdb loves.py
Trong lệnh trên, tên tệp
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
8, vì vậy bạn sẽ cần chèn tên tệp của bạn thay cho > /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
8.Lưu ý:
0 là một cờ và nó thông báo cho Python rằng một mô-đun cần phải được imported; cờ này được theo sau bởi tên của mô-đun, trong trường hợp của trên của mình là pdb. python -m pdb loves.py var1 var2 var3
python -m pdb loves.py var1 var2 var3
0 là một cờ và nó thông báo cho Python rằng một mô-đun cần phải được imported; cờ này được theo sau bởi tên của mô-đun, trong trường hợp của trên của mình là pdb.Chạy xong lệnh sẽ hiển thị như thế này:
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
Đầu ra sẽ luôn có cùng cấu trúc. Nó sẽ bắt đầu với đường dẫn thư mục đến tệp mã nguồn. Sau đó, trong ngoặc, nó sẽ cho biết số dòng từ tệp mà PDB hiện đang trỏ tới, trong trường hợp của mình là
python -m pdb loves.py var1 var2 var3
1. Dòng tiếp theo, bắt đầu bằng ký hiệu python -m pdb loves.py var1 var2 var3
2, cho biết dòng đang được trỏ đến.Để đóng PDB, chỉ cần nhập
python -m pdb loves.py var1 var2 var3
3 hoặc python -m pdb loves.py var1 var2 var3
4.Một vài điều cần lưu ý, nếu chương trình của bạn có các tham số đầu vào, bạn cũng có thể chuyển chúng qua command line. Ví dụ, nếu chương trình của mình yêu cầu 3 đầu vào từ người dùng, thì lệnh của mình sẽ như thế này:
python -m pdb loves.py var1 var2 var3
Tiếp tục, nếu trước đó bạn đã đóng PDB thông qua lệnh
python -m pdb loves.py var1 var2 var3
3 hoặc python -m pdb loves.py var1 var2 var3
4, sau đó chạy lại tệp code thông qua PDB. Sau đó, chạy lệnh sau trong command line PDB:[Pdb] list
Đầu ra trông như thế này:
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
Hiển thị 11 dòng đầu tiên của chương trình cho bạn, với dấu
python -m pdb loves.py var1 var2 var3
2 hướng về dòng hiện tại đang được debug. Tiếp theo, hãy thử lệnh này trong command line PDB.[Pdb] list 4, 6
Lệnh này sẽ chỉ hiển thị các dòng được chọn, trong trường hợp này là các dòng 4 đến 6. Đây là đầu ra:
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
[Pdb]
Debugging với Break points
Một thứ quan trọng tiếp theo mà chúng ta sẽ tìm hiểu là
python -m pdb loves.py var1 var2 var3
8. python -m pdb loves.py var1 var2 var3
8 thường được sử dụng cho các chương trình lớn hơn, nhưng để hiểu rõ hơn về nó, chúng ta sẽ tìm hiểu cách nó hoạt động dựa trên ví dụ cơ bản bên trên. python -m pdb loves.py var1 var2 var3
8 là các vị trí cụ thể mà chúng tôi khai báo trong code của mình. Code của tôi chạy đến vị trí đó và sau đó tạm dừng. Những điểm này được tự động gán số bởi PDB.Có các tùy chọn sau đây để tạo
python -m pdb loves.py var1 var2 var3
8:- Theo số dòng [By line number]
- Bằng cách khai báo hàm [By function declaration]
- Bởi một điều kiện [By a condition]
Để khai báo
python -m pdb loves.py var1 var2 var3
8 theo số dòng, hãy chạy lệnh sau trong commandline PDB:[Pdb] break loves.py:9
Lệnh này chèn một
python -m pdb loves.py var1 var2 var3
8 ở dòng code thứ 8, nó sẽ tạm dừng chương trình một khi nó chạy tới điểm đó. Đầu ra lệnh này được hiển thị là:List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
0Để khai báo các
python -m pdb loves.py var1 var2 var3
8 trên một hàm, hãy chạy lệnh sau:List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
1Để chèn một điểm dừng theo cách này, bạn phải khai báo nó bằng tên tệp và sau đó là tên hàm. Điều này xuất ra như sau:
List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
2Như bạn thấy,
python -m pdb loves.py var1 var2 var3
8 này đã được được tự động gán số 2 và số dòng là 4 - chính là tại dòng hàm được khai báo.python -m pdb loves.py var1 var2 var3
8 cũng có thể được khai báo bởi một điều kiện. Trong trường hợp đó, chương trình sẽ chạy cho đến khi điều kiện sai và sẽ tạm dừng khi điều kiện đó trở thành đúng. Chạy lệnh sau:List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
3Điều này sẽ theo dõi giá trị của biến
[Pdb] list
7 trong suốt quá trình thực thi và chỉ ngắt khi giá trị của nó là "Thi" ở dòng 6.Để xem tất cả các
python -m pdb loves.py var1 var2 var3
8 mà mình đã khai báo dưới dạng danh sách, hãy chạy lệnhList crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
4Kết quả sẽ có dạng:
List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
5Cuối cùng, làm thế nào chúng ta có thể vô hiệu hóa, kích hoạt và xóa một
python -m pdb loves.py var1 var2 var3
8 cụ thể tại bất kỳ trường hợp nào. Chạy lệnh sau:List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
6Lệnh trên sẽ vô hiệu hóa
python -m pdb loves.py var1 var2 var3
8 2, nhưng sẽ không xóa nó khỏi phiên debug.Bạn sẽ thấy số
python -m pdb loves.py var1 var2 var3
8 bị vô hiệu hóa.List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
7Cho phép xem lại danh sách tất cả các
python -m pdb loves.py var1 var2 var3
8 để xem giá trị "End" cho python -m pdb loves.py var1 var2 var3
8 2:List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
4Đầu ra:
List crush:
Lê
Thi
Thiên
Mỹ
code of loves:
1111112
2111014
3451524
4512244
9Để kích hoạt
python -m pdb loves.py var1 var2 var3
8 2:python -m pdb loves.py
0Và một lần nữa, đây là đầu ra:
python -m pdb loves.py
1Bây giờ, nếu bạn in danh sách tất cả các điểm break, giá trị "End" của breakpoint 2 sẽ hiển thị
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
5.Bây giờ chúng ta hãy xóa breakpoint 1:
python -m pdb loves.py
2Kết quả:
python -m pdb loves.py
3Nếu chúng ta in lại danh sách các breakpoint, thì bây giờ sẽ chỉ hiển thị 2 breakpoint. Hãy kiểm tra bằng lệnh
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
6.python -m pdb loves.py
4Đúng như mong đợi.
Trước khi làm điều tiếp theo, tôi muốn hiển thị ra kết quả khi chạy code cho đến khi breakpoint được đặt. Để làm điều đó, hãy xóa tất cả các breakpoint trước đó và khai báo một breakpoint khác thông qua commandline PDB:
Xóa tất cả các breakpoint
5python -m pdb loves.py
Sau đó, nhập "y" và nhấn "ENter". Bạn sẽ thấy kết quả xuất hiện:
6python -m pdb loves.py
Khai báo một breakpoint mới
Mình sẽ chạy cho đến khi giá trị của biến
7 bằng "Thi". Vì vậy, về cơ bản, chương trình sẽ tạm dừng trước chữ "Lê".[Pdb] list
3List crush: Lê Thi Thiên Mỹ code of loves: 1111112 2111014 3451524 4512244
Chạy cho đến breakpoint
Để chạy code, sử dụng
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
8, lệnh này sẽ thực thi code cho đến khi chạm breakpoint hoặc kết thúc:python -m pdb loves.py
8Bạn sẽ thấy:
python -m pdb loves.py
9Chương trình chạy cho đến breakpoint và tạm dừng, bây giờ tùy thuộc vào chúng ta muốn thay đổi bất cứ điều gì, kiểm tra các kiến hoặc nếu chúng ta muốn chạy tập lệnh cho đến khi hết hoàn thành. Hãy chạy lệnh
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
8.Kết quả:
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
0Nếu chúng ta in lại danh sách các breakpoint, thì bây giờ sẽ chỉ hiển thị 2 breakpoint. Hãy kiểm tra bằng lệnh
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
6.Đúng như mong đợi. Trước khi di chuyển về phía trước, hãy xóa tất cả các breakpoint bằng cách chạy lệnh
[Pdb] list 4, 6
0, sau đó nhập [Pdb] list 4, 6
1 vào commandline PDB.Trước khi làm điều tiếp theo, tôi muốn hiển thị ra kết quả khi chạy code cho đến khi breakpoint được đặt. Để làm điều đó, hãy xóa tất cả các breakpoint trước đó và khai báo một breakpoint khác thông qua commandline PDB:
Xóa tất cả các breakpoint
Sau đó, nhập "y" và nhấn "ENter". Bạn sẽ thấy kết quả xuất hiện:
Khai báo một breakpoint mới
Mình sẽ chạy cho đến khi giá trị của biến
[Pdb] list
7 bằng "Thi". Vì vậy, về cơ bản, chương trình sẽ tạm dừng trước chữ "Lê".python -m pdb loves.py
Chạy cho đến breakpoint
> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
2Để chạy code, sử dụng
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
8, lệnh này sẽ thực thi code cho đến khi chạm breakpoint hoặc kết thúc:> /home/nguyenmanh/projects/test/loves.py[1][]
-> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
[Pdb]
3Bạn sẽ thấy:
Chương trình chạy cho đến breakpoint và tạm dừng, bây giờ tùy thuộc vào chúng ta muốn thay đổi bất cứ điều gì, kiểm tra các kiến hoặc nếu chúng ta muốn chạy tập lệnh cho đến khi hết hoàn thành. Hãy chạy lệnh
1 -> list_crush = ['Lê', 'Thi', 'Thiên', 'Mỹ']
2 love_codes = [1111112, 2111014, 3451524, 4512244]
3
4 def show_list_crush[]:
5 print['List crush: ']
6 for crush in list_crush:
7 print[crush]
8
9 print["code of loves: "]
10 for code in love_codes:
11 print[code]
[Pdb]
8.Trong kết quả trên, có thể thấy chương trình tiếp tục từ breakpoint, chạy phần còn lại và sau đó khởi động lại để cho phép chúng ta debug thêm nếu muốn. Bây giờ chuyển sang phần tiếp nha.
Lưu ý quan trọng: Trước khi di chuyển về phía trước, hãy xóa tất cả các breakpoint bằng cách chạy lệnh
[Pdb] list 4, 6
0, sau đó nhập [Pdb] list 4, 6
1 vào commandline PDB.Chức năng Next và Step