无论你是资深的Python程序员,还是刚刚开始学习Python,你可能都遇到过语法错误的问题。一个小小的标点符号遗漏就能导致代码崩溃,而错误信息有时并不会提供足够的线索。
通过阅读本文,你可以通过实际示例来学习如何理解、避免和修复Python语法错误。
什么是Python中的语法错误?
语法错误是代码中不符合语法规则的部分。换句话说,当Python解释器无法识别代码中的语句结构时,就会发生语法错误。
每种语言都有自己的规则来确保内容的正确表达。我们不能省略某些单词或字母,因为这会改变其含义。编程语言也是如此,包括Python在内。你的代码必须遵循Python的语法规则,才能被正确理解和执行。
编程语言的作用是将人类语言翻译成机器语言。因此,代码的执行有特定的步骤。当你运行代码时,Python解释器会先将代码解析成更小的组件,然后将其翻译成字节码,最后执行它。
在解析过程中,解释器会检查代码是否有语法错误。当发现第一个语法错误时,它会给出一个SyntaxError的消息。
如何阅读Python语法错误
当你收到错误消息时,Python会尝试指出错误的根本原因。有时候,消息会准确地告诉你问题所在,但有时它可能不太清楚甚至让人困惑。这是因为Python会标记它无法理解的第一个位置,因此错误可能显示在实际错误之后的代码行中。
学会如何阅读Python错误消息可以节省大量时间和精力。下面我们来看一个引发两个语法错误的Python网络抓取代码示例:
prices = {"price1": 9.99, "price2": 13.48 "price3": 10.99, "price4": 15.01} price_found = False for key value in prices.items(): if 10 <= value <= 14.99: print(key + ":", value) price_found = True if not price_found: print("There are no prices between $10 and $14.99")
在这个例子中,我们有一个包含不同价格的字典。我们使用for循环查找并打印 10 美元到 14.99 美元之间的价格。price_found变量使用布尔值来确定是否在字典中找到这样的价格。
执行时,Python 会指出它遇到的第一个无效语法错误,尽管过程中还有另外两个错误。第一个错误消息如下所示:
黄色框中的信息可帮助我们确定错误的位置,绿色框包含有关错误本身的更多详细信息。完整消息可分为四个主要元素:
-
发生错误的文件的路径目录及名称;
-
首次遇到错误的行号和错误代码行;
-
插入符号 (^)指出错误的位置;
-
错误消息确定错误类型,后面跟着可能有助于解决问题的附加信息。
代码示例产生语法错误,该错误出现在代码的第一行——价格字典中。插入符号表示错误发生在“price2”:13.48和“price3”:10.99之间,无效语法消息表示我们可能忘记在字典中的项目之间添加逗号。就是这样!Python 解释器建议了正确的解决方案,所以让我们更新代码:
prices = {"price1": 9.99, "price2": 13.48, "price3": 10.99, "price4": 15.01}
现在,重新运行代码以查看第二个语法错误是什么:
这次,插入符号无法准确指出错误的位置,并且SyntaxError消息不包含有关可能解决方案的其他信息。在这种情况下,经验法则是检查插入符号之前的代码。在代码示例中,出现语法错误是因为for循环中的变量key和value之间缺少逗号。语法正确的代码行应如下所示:
for key, value in prices.items():
当谈到 Python 语法错误的原因时,有时没有足够的信息让您走上正确的轨道。例如上面的无效语法错误示例。因此,了解导致 Python 语法错误的一些常见原因有助于轻松解决它们。
语法错误的常见原因
通常,常见的 Python 语法错误是由代码中的这些无效性引起的:
-
标点符号放错位置、缺失或不匹配(括号、方括号、大括号、引号、逗号、冒号等);
-
拼写错误、放错位置或缺失的 Python 关键字;
-
变量名中有非法字符;
-
缩进不正确;
-
赋值运算符(=)使用不正确。
缺乏 Python 经验、复制粘贴错误和排版错误在这里起着重要作用。尤其是后者,因为排版错误很容易犯,而且很难发现,所以在生产过程中仔细检查代码是一种很好的做法。
无论如何,您可以在编码时采取其他步骤来减少出现语法错误的可能性。
如何避免 Python 语法错误?
-
使用集成开发环境 (IDE) 或代码编辑器,突出显示保留的 Python 关键字和错误,并在编写代码时建议修改。这是改进代码并避免 Python 中无效语法错误的首要步骤。
-
在编写代码时经常测试代码。这有助于从一开始就发现语法错误,并最大限度地降低以后重复犯同样错误的风险。
-
使用一致的缩进。不正确的缩进是 Python 中语法错误的常见原因之一,可以通过有意识地检查代码并使用突出显示缩进错误的 IDE 或代码编辑器来避免这种情况。
-
使用 linting 和 formatting 模块检查代码中的错误和样式。有些模块可以自动修复代码,节省您的时间和精力。当您只想在终端中运行 Python 而不需要 IDE 或代码编辑器时,linters 和 formatters 非常有用。一些值得一提的模块包括pycodestyle、pylint、pyflakes、Flake8和Black。
-
阅读 Python 文档。这确实是一个显而易见的建议,但Python 官方文档提供了许多有用的信息,不仅可以加深你的知识,还可以帮助您理解 Python 的语法和语法错误消息的含义。
请记住,这些步骤可以帮助您避免常见的 Python 语法错误,但不能消除它们。
即使您的代码在语法上是正确的,但代码运行时出现问题,也会出现异常。Python 运行时错误发生在代码执行期间,并会改变程序的正常流程。与语法错误(错误发生后会终止程序)不同,如果使用适当的异常处理程序,运行时错误可以继续运行程序。
此外,当代码在语法上有效且运行时没有错误,但输出却不是预期时,就会发生逻辑错误。虽然本文探讨了无效语法问题,但应该注意的是,SyntaxError 异常是更广泛的异常组的一部分。对于高级 Python 编程,建议了解其他错误及其处理方法。
如何修复语法错误
现在我们已经讨论了 Python 语法错误的常见原因以及避免这些错误的一般技巧,让我们看一些实际的代码示例并修复它们。
标点符号放错位置、缺失或不匹配
1. 确保圆括号()、方括号[]
list_of_URLs = ( 'https://example.com/1', 'https://example.com/2", 'https://example.com/3 ) print(list_of_URLs) # Error message File "<stdin>", line 3 'https://example.com/2", ^ SyntaxError: unterminated string literal (detected at line 3)
和大括号{}正确闭合。如果不闭合,Python 解释器会将第一个圆括号、方括号或大括号后面的所有内容视为单个语句。请查看此网页抓取代码示例,该示例向我们的网页爬虫工具发送一组抓取指令:
payload = { "url": "https://www.example.com/", "filters": { "crawl": [".*"], "process": [".*"], "max_depth": 1, "scrape_params": { "user_agent_type": "desktop", }, "output": { "type_": "sitemap" } } # Error message File "<stdin>", line 1 payload = { ^ SyntaxError: '{' was never closed
乍一看,似乎这个数据包已经用大括号闭合了,但Python解释器却抛出一个语法错误,表明情况并非如此。在这个特定的例子中,“filters”参数没有用大括号闭合,而解释器在回溯信息中并没有显示这一点。你可以通过闭合“filters”参数来修复这个错误:
payload = { "url": "https://www.amazon.com/", "filters": { "crawl": [".*"], "process": [".*"], "max_depth": 1 }, # Add the missing brace "scrape_params": { "user_agent_type": "desktop", }, "output": { "type_": "sitemap" } }
2. 确保使用正确的引号结束字符串。例如,如果您的字符串以单引号 ‘ 开头,则请在字符串末尾再次使用单引号。以下代码片段说明了这一点:
list_of_URLs = ( 'https://example.com/1', 'https://example.com/2", 'https://example.com/3 ) print(list_of_URLs) # Error message File "<stdin>", line 3 'https://example.com/2", ^ SyntaxError: unterminated string literal (detected at line 3)
这个例子中有两个错误,但正如你所见,解释器只显示了第一个语法错误。它准确地指出了问题所在,即字符串以单引号开始,却以双引号结束。
第二个错误在第三个示例URL中,该URL根本没有用引号闭合。语法正确的版本应该是这样的:
list_of_URLs = ( 'https://example.com/1', 'https://example.com/2', 'https://example.com/3' ) print(list_of_URLs)
当字符串内容本身包含引号时,请使用单引号‘、双引号“和/或三引号”'来指定字符串的开始和结束位置。例如:
print("In this example, there's a "quote within 'a quote'", which we separate with double and single quotes.") # Error message File "<stdin>", line 1 print("In this example, there's a "quote within 'a quote'", which we separate with double and single quotes.") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: invalid syntax. Perhaps you forgot a comma?
解释器显示了错误发生的位置,你可以看到插入符号在第二个双引号内结束。要修复这个语法错误,你可以用三引号(”' 或 “””)将整个字符串括起来:
print("""In this example, there's a "quote within 'a quote'", which we specify with double and single quotes.""")
3. 传递多个参数或值时,请务必使用逗号分隔它们。请考虑以下将 HTTP 标头封装在 headers 字典中的 Web 抓取示例:
headers = { 'Accept': 'text/html', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US, en;q=0.9' 'Connection': 'keep-alive' } # Error message File "<stdin>", line 5 'Connection': 'keep-alive' ^ SyntaxError: invalid syntax
同样,解释器没有准确显示问题所在,但通常你可以预期实际的语法错误发生在插入符号指向的位置之前。你可以通过在‘Accept-Language’参数后添加缺失的逗号来修复这个错误:
headers = { 'Accept': 'text/html', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US, en;q=0.9', 'Connection': 'keep-alive' }
4. 不要忘记在函数或复合语句(如 if、for、while、def 等)的末尾添加一个冒号 :。让我们看一个网络抓取的例子:
def extract_product_data() for url in product_urls response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') title = soup.find("h1").text price = soup.find("span", {"itemprop": "price"}).text product_data.append({ "title": title, "price": price, }) # Error message File "<stdin>", line 1 def extract_product_data() ^ SyntaxError: expected ':'
这次,解释器显示了发生错误的确切位置,并提示了可以采取哪些措施来解决问题。在上面的例子中,def函数和for循环缺少冒号,因此我们可以更新代码:
def extract_product_data(): for url in product_urls:
拼写错误、放错位置或缺失 Python 关键字
1. 确保你没有使用保留的 Python 关键字来命名变量和函数。如果你不确定某个单词是否是 Python 关键字,请使用Python 中的关键字模块检查它,或在保留关键字列表中查找它。许多 IDE(如 PyCharm 和 VS Code)都会突出显示保留关键字,这非常有用。下面的代码片段使用保留关键字pass来保存密码值,这会导致语法错误消息:
user = 'username1' pass = 'password1' # Error message File "<stdin>", line 2 pass = 'password1' ^ SyntaxError: invalid syntax
2. 确保你没有拼错 Python 关键字。例如:
import time from requests impotr Session # Error message File "<stdin>", line 2 from requests impotr Session ^^^^^^ SyntaxError: invalid syntax
此代码示例尝试从请求库导入Session对象。但是,Python 关键字import拼写错误为impotr,从而引发了无效语法错误。
3. 将 Python 关键字放在不该出现的位置也会引起错误。确保 Python 关键字的语法顺序正确,并遵循该关键字的特定规则。请考虑以下示例:
import time import Session from requests # Error message File "<stdin>", line 2 import Session from requests ^^^^ SyntaxError: invalid syntax
这里,我们看到一个无效语法错误,因为 Python 关键字from不遵循正确的语法顺序。修复后的代码应如下所示:
import time from requests import Session
变量名称中的非法字符
Python 变量必须遵循一定的命名约定:
1. 变量名不能使用空格。最好的解决方案是使用下划线字符。例如,如果你想要一个名为“two words”的变量,它应该写成two_words、twowords、TwoWords、twoWords或Twowords。
2. 变量区分大小写。这意味着example1和Example1是两个不同的变量。在创建变量并在代码中调用它们时,请考虑到这一点。
3. 不要用数字开头变量。Python 会给出语法错误:
response1 = requests.get(url) 2response = requests.post(url) # Error message File "<stdin>", line 2 2response = requests.post(url) ^ SyntaxError: invalid decimal literal
正如你所见,解释器允许在变量名中使用数字,但变量名不能以数字开头。
4. 变量名只能使用字母、数字和下划线。变量名中使用任何其他字符都会产生语法错误。
缩进错误
1. 请记住,某些Python命令(如复合语句和函数)需要通过缩进来定义命令的范围。因此,确保代码中的此类命令正确缩进。例如:
prices = (16.99, 13.68, 24.98, 14.99) def print_price(): for price in prices: if price < 15: print(price) print_price() # Error message 1 File "<stdin>",line 6 if price < 15: ^ IndentationError: expected an indented block after 'for' statement on line 5 # Error message 2 File "<stdin>", line 7 print(price) ^ IndentationError: expected an indented block after 'if' statement on line 6
第一条错误消息表明if语句需要缩进块。修复该问题并运行代码后,我们遇到第二条错误消息,该消息告诉我们print语句超出了if语句的范围,需要再次缩进。使用正确的缩进修复代码:
prices = (16.99, 13.68, 24.98, 14.99) def print_price(): for price in prices: if price < 15: print(price) print_price()
2. 使用一致的缩进标记:全部使用空格或全部使用制表符。不要混淆它们,因为这会降低代码的可读性,从而使得仅通过查看代码就很难找到错误的缩进。大多数 Python IDE 会在运行代码之前突出显示缩进错误,因此您可以自动重新格式化文件以修复缩进。
让我们采用上面的代码示例,并通过在if语句前添加一个空格来修复第一个错误消息:
prices = (16.99, 13.68, 24.98, 14.99) def print_price(): for price in prices: if price < 15: print(price) print_price()
代码运行正常,没有错误,并打印出正确的结果。但是,您可以看到空格和制表符的混合使代码更难阅读。使用这种方法可能会带来不必要的语法错误,而这些错误可以通过在整个代码中坚持使用空格或制表符来避免。
赋值运算符 (=) 使用不正确
1. 确保不要使用赋值运算符=为函数或文字赋值。您只能为变量赋值。以下是一些示例的概述:
"price" = 10.98 # Error message File "<stdin>", line 1 "price" = 10.98 ^^^^^^^ SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='?
字符串“price”不能充当变量,因此必须删除引号:
price = 10.98
在下面的例子中,我们要检查值10.98是否是浮点类型:
price = 10.98 type(price) = float # Error message File "<stdin>", line 2 type(price) = float ^^^^^^^^^^^ SyntaxError: cannot assign to function call here. Maybe you meant '==' instead of '='
Python解释器会抛出一个错误,因为赋值运算符不能用于将值赋给一个函数。正确的方法是使用以下代码示例之一:
price = 10.98 print(type(price)) # or price = 10.98 is_float = type(price) == float print(is_float)
2. 使用冒号: 而不是赋值运算符=为字典赋值。让我们采用之前的代码示例并对其进行修改,使其错误地使用赋值运算符而不是冒号:
headers = { 'Accept' = 'text/html', 'Accept-Encoding' = 'gzip, deflate, br', 'Accept-Language' = 'en-US, en;q=0.9', 'Connection' = 'keep-alive' } # Error message File "<stdin>", line 2 'Accept' = 'text/html', ^^^^^^^^ SyntaxError: cannot assign to literal here. Maybe you meant '==' instead of '='?
3. 根据对象的值进行比较时使用==。例如:
price_1 = 200.99 price_2 = 200.98 compare = (price_1 = price_2) print(compare) # Error message File "<stdin>", line 4 compare = (price_1 = price_2) ^^^^^^^^^^^^^^^^^ SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?
你可以通过在price_1和price_2之间使用双等号==而不是=来解决该问题,这将打印正确的结果。
总 结
Python中的语法错误有时很难解决,这取决于具体的错误类型。不过,当你了解错误回溯的工作原理,知道这些错误的常见原因和解决方法后,就可以大大减少调试所需的时间和精力。希望这篇文章能帮助你走上正确的道路,开始编写没有语法错误的Python代码。