Hướng dẫn syntax error print python - lỗi cú pháp print python
Python nổi tiếng vì cú pháp đơn giản của nó. Tuy nhiên, khi bạn đang học Python lần đầu tiên hoặc khi bạn đến với Python với một nền tảng vững chắc ở ngôn ngữ lập trình khác, bạn có thể tìm hiểu những thứ mà Python không cho phép. Nếu bạn nhận được lỗi 1 khi chạy code của bạn thì bài viết này sẽ giúp đỡ bạn giải quyết vấn đề này. Xuyên suốt tutorial, bạn sẽ thấy các ví dụ điển hình về lỗi cú pháp trong Python hà học cách giải quyết chúng.Đến cuối tutorial này, bạn có thể:
Invalid Syntax in PythonKhi bạn chạy code, đầu tiên trình biên dịch sẽ phân tích (parse) để convert nó thành Python byte code - đoạn code sau đó được chạy. Trình biên dịch sẽ tìm các lỗi về cú pháp trong bước đầu tiên trong quá trình xử lý chương trình, hay còn gọi là bước phân tích (parsing stage). Nếu trình biên dịch không thể parse đoạn code thành công thì có nghĩa là bạn đã sử dụng sai cú pháp ở đâu đó trong code của bạn. Trình biên dịch sẽ cố gắng chỉ cho bạn thấy chỗ mà lỗi đó xảy ra. Khi bạn tiếp Python lần đầu tiên, bạn có thể bị nản khi bạn lỗi 1. Python sẽ giúp bạn xác định chỗ mà bạn sử dụng sai cú pháp nhưng traceback nó đưa ra có thể khó hiểu một chút. Thi thoảng, code nó trỏ tới hoàn toàn hợp lý.
Bạn không thể xử lý lỗi cú pháp như các exception khác. Thậm chí, nếu bạn cố gắng đưa đoạn code sai cú pháp vào trong một khối 5, bạn vẫn sẽ trình biên dịch raise lên lỗi 1.SyntaxError Exception and TracebackKhi trình biên dịch gặp phải lỗi cú pháp, Python sẽ raise lên exception 7 và cung cấp trace back với một số thông tin hữu ích để giúp bạn debug. Đây là đoạn code chứa lỗi cú pháp:
Bạn có thể thấy cú pháp không hợp lệ ở trong dict dòng 4. Mục thứ hai, 8, thiếu dấu phẩy. Nếu bạn chạy đoạn code, bạn sẽ thu được traceback sau:
Chú ý rằng traceback sẽ chỉ ra lỗi ở dòng 5, chứ không phải 4. Trình biên dịch Python đã cố chỉ ra vị trí lỗi. Tuy nhiên, nó chỉ có thể trỏ tới nơi nó bắt được lỗi đầu tiên. Khi nhận được traceback và traceback trông có ý nghĩa, bạn cần nhìn loại đoạn code để xác định chỗ sai. Trong ví dụ bên trên, không có với đề với việc thiếu dấu phẩy mà phụ thuộc vào việc cái gì theo sau nó. Ví dụ, việc không có dấu phẩy sau 9 ở dòng 5 chẳng ảnh hưởng gì. Nhưng một khi trình biên dịch bắt gặp điều gì đó bất ổn, nó chỉ có thể trỏ ngay tới dòng code đầu tiên mà nó không hiểu.
Có một vài thành phần của 1 có thể giúp bạn xác định vị trí lỗi:
Trong ví dụ trên, file name là 2, line number là 3 và caret trỏ vào dấu nháy đơn của key 4. Traceback 1 có thể không chỉ ra vấn đề thực sự nhưng nó sẽ chỉ tới vị trí đầu tiên mà trình biên dịch không hiểu.Có hai exception khác bạn có thể sẽ thấy Python raise lên. Nó tương tự như 1 nhưng dưới những cái tên khác:
Những exception này đều kế thừa từ 1 nhưng chúng là những trường hợp đặc biệt liên quan đến indentation (thụt đầu dòng). 7 được raise lên khi các mức indent không khớp nhau. Còn 8 xuất hiện khi code của bạn sử dụng cả tab và space trong cùng một file. Chúng ta sẽ xét kỹ hơn đến những exception này trong phần sau.Common Syntax ProblemsKhi chúng ta bắt gặp 1 lần đầu tiên, việc biết lý do lỗi xảy ra và cách fix nó thực sự hữu ích. Trong các phần tiếp theo, chúng ta sẽ thấy một số lý do phổ biến mà 1 có thể được raise lên và cách bạn có thể fix chúng.Misusing the Assignment Operator (=)Có vài trường hợp trong Python mà bạn không để gán các object ví dụ như với chuỗi và lời gọi hàm:
Ví dụ đầu tiên cố gắng gán giá trị 3 cho lời gọi 5. Message 1 rất hữu ích trong trường hợp này. Nó nói rằng là bạn không thể gán một giá trị cho một lời gọi hàm.Ví dụ thứ hai và thứ ba cố gắng gái một string với một số nguyên cho các chuỗi. Quy tắc tương tự đúng với các giá trị chuỗi khác. Một lần nữa, traceback chỉ ra vấn đề xảy ra khi bạn cố gắng gán một giá trị cho một chuỗi.
Có lẽ là bạn sẽ chẳng bao giờ có ý định gán một giá trị cho một chuỗi hoặc lời gọi hàm. Các lỗi trên xảy ra chỉ khi bạn vô tình quên mất một dấu "=" khi bạn muốn thực hiện phép so sánh:
Đa số các trường hợp, khi Python nói rằng bạn đang thực hiện phép gán với một object mà không thể được gán, đầu tiên bạn nên kiểm tra chắc chắn rằng xem câu lệnh là một lệnh gán hay là một biểu thức Boolean. Bạn cũng có thể gặp vấn đề này khi bạn đang cố gắng gán một giá trị với các keyword. Chúng ta sẽ đề cập đến trường hợp này trong mục sau. Misspelling, Missing, or Misusing Python KeywordsCác keyword trong Python là một tập các protected word có ý nghĩa đặc biệt trong Python. Đây là những từ khóa bạn không thể sử dụng như là các định danh, biến hoặc tên hàm. Chúng là một phần của ngôn ngữ và chỉ có thể sử dụng trong ngữ cảnh mà Python cho phép.protected word có ý nghĩa đặc biệt trong Python. Đây là những từ khóa bạn không thể sử dụng như là các định danh, biến hoặc tên hàm. Chúng là một phần của ngôn ngữ và chỉ có thể sử dụng trong ngữ cảnh mà Python cho phép. Những trường hợp mà bạn có thể nhầm lẫn sử dụng các keyword:
Nếu bạn viết sai chính tả, bạn sẽ thấy lỗi 1. Ví dụ đầy là điều xảy ra khi bạn viết sai keyword 8:
Message là 9 - không quá hữu ích. Traceback trỏ tới vị trí đầu tiên mà Python phát hiện có cái gì đó sai. Để fix các lỗi kiểu như này, hãy chắc chắn rằng một keyword đều đúng.Một vấn đề phổ biến khác chính là việc bạn quên keyword:
Một lần nữa, message lại không hữu ích nhưng traceback lại trỏ tới đúng vị trí. Nếu bạn di chuyển dấu mũ ngược lại bạn sẽ đấy keyword 0 bị thiếu trong cú pháp của vòng lặp 8.Bạn cũng có thể sử dụng sai protected keyword. Hãy nhớ rằng, các keyword chỉ được sử dụng trong một số trường hợp nhất định. Nếu bạn sử dụng sai chúng bạn cũng sẽ nhận được lỗi sai cú pháp. Một ví dụ điển hình là việc sử dụng 2 hoặc 3 ngoài vòng lặp. Điều này có thể dễ dàng xảy ra khi bạn di chuyển một đoạn code ra khỏi một vòng lặp:
Ở đây, Python đã làm tốt việc thông báo chính xác lỗi cho bạn biết. Message " 4" và " 5" giúp bạn biết việc mình cần làm.Một ví dụ khác là nếu bạn cố gắng gán một keyword cho một biến hoặc sử dụng keyword để khai báo hàm:
Nếu bạn thử gắn một giá trị cho 6 hoặc khi bạn định nghĩa một hàm với tên 6, bạn sẽ gặp lỗi 1 và thấy message 9 một lần nữa.Giải quyết lỗi cú pháp này có thể khó hơn một chút bởi đoạn code nhìn bên ngoài trông thì khá ổn. Nếu code trông ổn mà bạn vẫn gặp lỗi 1 thì bạn nên cân nhắc kiểm tra tên biến và hàm mà bạn muốn sử dụng.Danh sách các protected keyword sẽ thay đổi theo phiên bản của Python. Ví dụ trong Python 3.6 bạn có thể sử dụng 1 làm tên biến hoặc tên hàm nhưng trong Python 3.7 thì nó lại nằm trong danh sách keyword. Bây giờ, nếu bạn thử sử dụng 1 làm tên biến hoặc tên hàm, lỗi 1 sẽ bị raise lên nếu bạn sử dụng Python 3.7 hoặc cao hơn.Một ví dụ khác của vấn đề này chính là 4 - có sự khác nhau giữa Python 2 và 3:
4 là một keyword trong Python 2 nên bạn không thể gán giá trị cho nó. Tuy nhiên trong Python 3, nó là một hàm có sẵn có thể được gán các giá trị.Bạn có thể chạy code sau để thấy một danh sách keyword trong phiên bản Python mà bạn sử dụng:
7 là một hàm hữu ích dùng để kiểm tra xem một từ có là keyword hay không:
Missing Parentheses, Brackets, and QuotesThông thường, nguyên nhân gây ra lỗi cú pháp trong Python là do thiếu dấu đơn, ngoặc vuông hoặc dấu nháy đơn/kép đóng. Những thiếu xót này khó phát hiện ra ở những dòng dài mà có nhiều dấu ngoặc đơn lồng nhau hoặc ở những khối code nhiều dòng. Bạn có thể phát hiện ra điều này nhờ sự giúp đỡ của traceback: 0Ở đây, traceback chỉ ra chỗ code không hợp lệ là ở vị trí 8. Để fix lỗi này, bạn có thể sử dụng hai cách:
Một sai lầm thường gặp khác là quên đóng string: 1Lần này, dầu mũ trong traceback trỏ chính xác tới vị trí code có vấn đề. Thông báo 1, " 3", đã cụ thể và hữu ích hơn một chút trong việc xác định vấn đề. Điều này cũng có nghĩa là trình biên dịch Python đã đi tới tận cùng của dòng code đó. Để fix lỗi này, hãy đóng string với dấu nháy mà bạn đã sử dụng để mở string. Trong trường hợp này là dấu nháy kép 4.Việc thiếu dấu nháy trong các statement thuộc một f-string có thể dẫn tới lỗi cú pháp: 2Ở đây, việc tham chiếu tới dict 5 bên trong f-string bị thiếu dấu nháy kép đóng ở tham chiếu key. Traceback nhận được là: 3Python xác định vấn đề và cho bạn biết vấn đề nằm ở trong f-string. Message "unterminated string" cũng chỉ ra vấn đề là gì. Dấu mũ trong trường hợp này chỉ trỏ tới vị trí bắt đầu của f-string. Việc này có thể không có ý nghĩa khi mà dấu mũ trỏ tới khu vực của f-string nhưng nó lại không thu hẹp vị trí mà chúng ta cần quan tâm. Có một string chưa kết thúc bên trong f-string. Bạn chỉ việc tìm ra nó. Để fix lỗi này, hãy đảm bảo rằng tất cả các dấu nháy trong f-string và ngoặc nhọn phải đầy đủ. Lỗi tương tự xảy ra khi thiếu ngoặc đơn và ngoặc vuông. Ví dụ, nếu bạn quên dấu ngoặc vuông dùng để đóng một list, Python sẽ phát hiện và trỏ tới đó. Tuy nhiên, không có nhiều sự khác biệt trong những trường hợp này. Trong ví dụ đầu tiên, chúng ta quên dấu ngoặc vuông đóng: 4Khi chạy đoạn code này, bạn sẽ được nhắc nhở rằng có lỗi khi gọi 6: 5Điều xảy ra ở đây chính là việc Python nghĩ là list gồm ba phần tử: 7, 8 và 9. Python sử dụng khoảng trắng (whitespace) để nhóm các thứ lại với nhau và bởi vì không có dấu phẩy và ngoặc vuông ngăn 0 với 1, Python gộp chúng lại thành phần tử thứ ba của list.Một biến thể nữa là thêm một dấu phẩy sau phần tử cuối cùng của list trong khi vẫn quên dấu ngoặc vuông đóng: 6 Bây giờ bạn nhận được một traceback khác: 7Trong ví dụ trước đó, 0 và 1 được nhóm lại thành một phần tử nhưng ở đây bạn thấy dấu phẩy sẽ ngăn cách chúng. Bây giờ việc gọi 1 được thêm vào như là phần tử thứ tư của list và Python chạy tới cuối file mà không có dấu ngoặc vuông đóng. Traceback nói cho bạn biết rằng Python đã đọc hết file (EOF) nhưng nó vẫn mong chờ một cái gì đó khác.Trong ví dụ này, Python mong chờ một dấu ngoặc vuông đóng 5 nhưng dòng được nhắc và dấu mũ không thực sự hữu ích. Việc thiếu dấu ngoặc đơn hoặc dấu ngoặc đơn khiến Python rất khó để nhận ra. Đôi khi điều duy nhất bạn có thể làm là bắt đầu từ dấu mũ và quay ngược lại cho đến khi bạn phát hiện ra những thiếu sót.Mistaking Dictionary SyntaxTrước đó bạn đã thấy rằng bạn có thể gặp lỗi 1 nếu bạn quên dấu phẩy ở một phần tử dict. Một dạng khác của lỗi cú pháp với dict là việc sử dụng dấu "=" để ngăn cách các key và value thay vì ":": 8 Một lần nữa thông báo lỗi lại không hữu ích. Tuy nhiên, dòng nhắc lại và dấu mũ lại rất hữu ích! Chúng trỏ tới đúng ký tự có vấn đề. Để fix lỗi này, bạn có thể thay thế các dấu "=" với dấu ":". Bạn cũng có thể chuyển sang dùng 7: 9Bạn có thể sử dụng 7 để khai báo dict nếu cú pháp này hữu ích hơn.Using the Wrong IndentationCó hai class con của 1 dành riêng cho các vấn đề về indentation:
Trong khi các ngôn ngữ lập trình khác sử ngoặc nhọn để khai báo một khối code, Python lại sử dụng 00 (khoảng trắng). Python sẽ raise lên lỗi 7 nếu có một dòng code trong khối có số khoảng trắng không đúng: 0Điều này có thể khá khó để phát hiện nhưng dòng thứ 5 chỉ bị thụt có hai khoảng trắng. May thay Python lại dễ dàng phát hiện và nói cho bạn biết vấn đề là gì: 1Mặc dù traceback trông khá giống traceback của 1, nó thực tế lại là một 7. Thông báo lỗi rất hữu ích. Nó nói cho bạn biết mức indentation của dòng code không khớp các mức indentation khác. Bạn có thể sửa lỗi này một cách nhanh chóng bằng cách đảm bảo rằng đoạn code được thụt lùi sao cho đúng mức indentation mong muốn.Một loại 1 khác là 8 - error nói cho bạn biết rằng có một dòng có sử dụng tab hoặc space cho mục đích indentation trong khi cái còn lại được dùng ở một nơi khác trong file. Điều này có thể bị bỏ qua cho đến khi Python chỉ ra lỗi đó cho bạn biết!Nếu tab size trùng với số khoảng trắng trong mỗi mực indentation thì mọi thứ chẳng có vẻ gì lạ. Tuy nhiên, nếu một dòng được indent bằng space và một dòng khác lại được indent với tab thì Python sẽ chỉ cho bạn thấy vấn đề: 2Ở đây, dòng 5 được indent với một ký tự tab gồm 4 space. Khối code này có thể nhìn có vẻ hoàn hảo hoặc hoàn toàn sai, tùy vào setting hệ thống của bạn. Tuy nhiên, Python sẽ để ý vấn đề này ngay lập tức. Nhưng trước khi bạn chạy đoạn code để xem Python sẽ nói cho bạn biết cái gì sai, hãy xem ví dụ sau: 3Chú ý là sự khác biệt trong hiển thị giữa ba ví dụ trên. Trừ dòng 5 sử dụng single tab thì các dòng code khác sử dụng 4 space cho một mức indentation. Độ rộng của tab thay đổi dựa vào tab width setting:tab width setting:
Khi bạn chạy đoạn code, bạn sẽ nhận được lỗi và traceback sau: 4Chú ý rằng ở đây ta nhận được 8 thay vì 1. Python chỉ ra dòng có vấn đề và cung cấp cho bạn một thông báo hữu ích. Nó nói cho bạn rằng tab và space bị sử dụng lẫn lộn cho indentation trong cùng một file.Giải pháp cho vấn đề này là sử dụng hoặc là tab hoặc là space cho indentation, chứ không phải là cả hai. Defining and Calling FunctionsBạn có thể gặp lỗi cú pháp khi bạn định nghĩa hoặc gọi hàm. Ví dụ, bạn sẽ thấy SyntaxError nếu bạn sử dụng ";" thay vì ":" ở cuối cuối nghĩa hàm: 5Traceback ở đây rất hữu ích với việc dấu mũ trỏ tới đúng ký tự gây ra lỗi. Bạn có thể xóa xổ lỗi này bằng cách chuyển sang sử dụng ":". Hơn nữa, các keyword argument trong định nghĩa hàm và gọi hàm cũng cần phải đúng vị trí. Keyword argument luôn đến sau các positional argument: 6Ở đây, một lần nữa, tin nhắn lỗi lại rất hữu ích khi nói chỉ rõ cho bạn thấy vị trí lỗi. Changing Python VersionsThi thoảng, code chạy tốt ở một phiên bản Python nhưng lại bị lỗi ở các version mới hơn. Điều này là vì những thay đổi trong cú pháp ngôn ngữ. Ví dụ điển hình nhất chính là lệnh 4 khi nó chuyển mình từ một keyword trong Python 2 thành một hàm built-in trong Python 3: 7Đây là một trong các ví dụ mà tin nhắn lỗi cho 1 được đưa ra có ý nghĩa nhất! Không chỉ nói cho bạn biết là bạn đang thiếu các dấu ngoặc đơn mà còn đưa ra giải pháp cho bạn.Một vấn đề khác bạn có thể gặp chính là khi bạn đọc hoặc học về các cú pháp hợp lệ trong phiên bản mới hơn nhưng lại không hợp lệ trong phiên bản mà bạn đang dùng. Một ví dụ của việc này chính là cú pháp f-string - nó chỉ tồn tại trong các phiên bản từ 3.7 trở về sau: 8Trong các phiên bản Python trước 3.6, trình biên dịch không hề hiểu gì về f-string và sẽ chỉ đưa ra một thông báo chung chung là "invalid syntax". Trong trường hợp này, vấn đề là code trông thì rất ổn nhưng nó lại được chạy với Python phiên bản cũ. Cú pháp Python đang tiếp tục thay đổi, do đó sẽ có những tính năng mới được giới thiệu trong Python 3.8:
Nếu bạn muốn thử các tính năng mới này thì bạn hãy chắc chắn rằng mình sử dụng môi trường Python 3.8. Nếu không thì bạn sẽ gặp lỗi 1.Python 3.8 cũng cung cấp 16 mới. Bạn sẽ thấy cảnh báo này trong các trường hợp mà cú pháp hợp lệ nhưng vẫn có chút nghi ngờ. Ví dụ như khi bạn thiếu dấu "," giữa hai tuple trong một list. Việc làm như vậy có thể là hợp lệ về mặt cú pháp trong các phiên bản Python trước 3.8, nhưng code sẽ raise lên lỗi 17 bởi vì một tuple là không callable (không thể gọi): 9 17 này có nghĩa là bạn không thể gọi một tuple như với một hàm - điều mà trình biên dịch nghĩ bạn đang cố gắng làm.Trong Python 3.8, đoạn code này sẽ vẫn raise lên lỗi 1 nhưng bây giờ bạn sẽ thấy một 20 nói rằng bạn cần phải giải quyết vấn đề: 0Lời nhắn kèm theo 16 thậm chí còn chỉ cho bạn hướng giải quyết vấn đề!ConclusionTrong tutorial này, bạn đã thấy được các thông tin mà traceback của 1 cung cấp cho bạn. Bạn cũng đã thấy được các ví dụ về lỗi cú pháp và giải pháp cho chúng.Khi viết code, bạn thử sử dụng một IDE hỗ trợ việc soát lỗi và cung cấp feedback hữu ích. Nếu bạn đưa những đoạn code này vào một trình IDE tốt, nó sẽ highlight các lỗi cú pháp cho bạn thấy. Việc gặp lỗi cú pháp 1 khi bạn đang học Python có thể khiến bạn nản lòng nhưng bây giờ bạn đã hiểu được các tin nhắn từ traceback và các dạng lỗi cú pháp trong Python mà bạn có thể gặp. Lần say khi gặp một lỗi 1, bạn sẽ sửa lỗi đó nhanh hơn!Nguồn: https://realpython.com/invalid-syntax-python/ |