Chr*_*ean 38 python error-handling code-formatting exception indentation
我有一个Python脚本:
if True:
if False:
print('foo')
print('bar')
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试运行我的脚本时,Python提出了一个IndentationError:
File "script.py", line 4
print('bar')
^
IndentationError: unindent does not match any outer indentation level
Run Code Online (Sandbox Code Playgroud)
我一直在玩我的程序,我还能够产生其他三个错误:
IndentationError: unexpected indentIndentationError: expected an indented blockTabError: inconsistent use of tabs and spaces in indentation这些错误意味着什么?我究竟做错了什么?我该如何修复我的代码?
Chr*_*ean 57
在Python中,缩进用于分隔代码块.这与使用花括号{}来分隔Java,Javascript和C等块的许多其他语言不同.因此,Python用户必须密切关注它们缩进代码的时间和方式,因为空白很重要.
当Python遇到程序缩进的问题时,它会引发一个名为IndentationError或的异常TabError.
有点历史
Python 的创建者Guido van Rossum在Python的历史文章中{}概述了Python使用缩进的原因与可以说是更常被接受的花括号的历史原因:
Python使用缩进直接来自ABC,但这个想法并非源于ABC - 它已经由Donald Knuth推广,并且是一个众所周知的编程风格概念.(occam编程语言也使用它.)然而,ABC的作者确实发明了使用冒号将引入子句与缩进块分开.在没有结肠的早期用户测试之后,发现缩进的含义不清楚初学者被教授编程的第一步.结肠的加入明显地澄清了它:结肠以某种方式引起了对后面的注意,并以恰当的方式将它们之前和之后的短语联系在一起.
缩进Python代码的基本规则(考虑到将整个程序视为"基本块")是:基本块中的第一个语句,以及后面的每个后续语句必须缩进相同的数量.
从技术上讲,以下Python程序是正确的:
def perm(l):
# Compute the list of all permutations of l
if len(l) <= 1:
return [l]
r = []
for i in range(len(l)):
s = l[:i] + l[i+1:]
p = perm(s)
for x in p:
r.append(l[i:i+1] + x)
return r
Run Code Online (Sandbox Code Playgroud)
但是,正如您可能从上面可以看出的那样,随机缩进您的代码使得极难阅读并遵循程序流程.最好是保持一致并遵循一种风格.
PEP8 - Python样式指南 - 建议每个缩进级别应使用四个空格:
每个缩进级别使用4个空格.
也就是说,每个开始新块的语句和新块中的每个后续语句都应该从当前缩进级别缩进四个空格.以下是根据PEP8样式指南缩进的上述程序:
def perm(l):
# Compute the list of all permutations of l
if len(l) <= 1:
return [l]
r = []
for i in range(len(l)):
s = l[:i] + l[i+1:]
p = perm(s)
for x in p:
r.append(l[i:i+1] + x)
return r
Run Code Online (Sandbox Code Playgroud)
Python意识到有些人仍然喜欢使用制表符而不是空格,遗留代码可能使用制表符而不是空格,所以它允许使用制表符作为缩进.PEP8涉及这个主题:
空格是首选的缩进方法.
选项卡应仅用于与已使用选项卡缩进的代码保持一致.
但请注意,一个重要的警告是不要同时使用制表符和空格来缩进.这样做会导致各种奇怪的难以调试缩进错误.Python将选项卡扩展到下一个第8列,但如果您的编辑器设置为4列的选项卡大小,或者您使用空格和选项卡,则可以轻松生成在编辑器中看起来很好的缩进代码,但Python会拒绝跑步.Python 3编译器显式拒绝任何包含选项卡和空格混合的程序,通常是通过引发TabError.但是,默认情况下,Python 2中仍然允许混合制表符和空格,但强烈建议不要使用此"功能".使用-t和-tt命令行标志强制Python 2分别发出警告或(最好)错误.PEP8还讨论了这个主题:
Python 3不允许混合使用制表符和空格来缩进.
使用制表符和空格的混合缩进的Python 2代码应该转换为仅使用空格.
当使用-t选项调用Python 2命令行解释器时,它会发出有关非法混合制表符和空格的代码的警告.使用-tt时,这些警告会出错.强烈推荐这些选项!
问题
如果语句不必要地缩进或其缩进与同一块中的前语句的缩进不匹配,则会发生此错误.例如,下面程序中的第一个语句不必要地缩进:
>>> print('Hello') # this is indented
File "<stdin>", line 1
print('Hello') # this is indented
^
IndentationError: unexpected indent
Run Code Online (Sandbox Code Playgroud)
在此示例中,块中的can_drive = True行if与任何前一个语句的缩进不匹配:
>>> age = 10
>>> can_drive = None
>>>
>>> if age >= 18:
... print('You can drive')
... can_drive = True # incorrectly indented
File "<stdin>", line 3
can_drive = True # incorrectly indented
^
IndentationError: unexpected indent
Run Code Online (Sandbox Code Playgroud)
固定
此错误的修复方法是首先确保有问题的行甚至需要缩进.例如,上面的示例使用print可以修复只是简单的行:
>>> print('Hello') # simply unindent the line
Hello
Run Code Online (Sandbox Code Playgroud)
但是,如果您确定该行确实需要缩进,则缩进需要与同一块中的前一个语句的缩进匹配.在上面的第二个例子中if,我们可以通过确保行与can_drive = True缩进到与if正文中的前一个语句相同的级别来修复错误:
>>> age = 10
>>> can_drive = None
>>>
>>> if age >= 18:
... print('You can drive')
... can_drive = True # indent this line at the same level.
...
Run Code Online (Sandbox Code Playgroud)
问题
当Python看到复合语句的"标题"时会发生此错误,例如if <condition>:或者从未定义while <condition>:复合语句的主体或块.例如,在下面的代码中我们开始if声明,但我们从不为语句定义一个主体:
>>> if True:
...
File "<stdin>", line 2
^
IndentationError: expected an indented block
Run Code Online (Sandbox Code Playgroud)
在第二个例子中,我们开始编写for循环,但是我们忘记缩进for循环体.所以Python仍然期望for循环体的缩进块:
>>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
... print(name)
File "<stdin>", line 2
print(name)
^
IndentationError: expected an indented block
Run Code Online (Sandbox Code Playgroud)
评论不算作正文:
>>> if True:
... # TODO
...
File "<stdin>", line 3
^
IndentationError: expected an indented block
Run Code Online (Sandbox Code Playgroud)
固定
此错误的修复是简单地包含复合语句的主体.
如上所示,新用户的一个常见错误是他们忘记了缩进身体.如果是这种情况,请确保复合语句正文中包含的每个语句都在复合语句的开头缩进到同一级别.以上是修复的上述示例:
>>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
... print(name) # The for loop body is now correctly indented.
...
sarah
lucy
michael
Run Code Online (Sandbox Code Playgroud)
另一个常见的情况是,由于某种原因,用户可能不想为复合语句定义实际的主体,或者可以注释掉主体.在这种情况下,pass可以使用该语句.该pass语句可以在Python期望一个或多个语句作为占位符的任何地方使用.从以下文档pass:
pass是一个空操作 - 当它被执行时,没有任何反应.当语法需要语句但不需要执行任何代码时,它可用作占位符,例如:
Run Code Online (Sandbox Code Playgroud)def f(arg): pass # a function that does nothing (yet) class C: pass # a class with no methods (yet)
以下是if使用pass关键字修复语句的上述示例:
>>> if True:
... pass # We don't want to define a body.
...
>>>
Run Code Online (Sandbox Code Playgroud)
问题
当您取消注释语句时会发生此错误,但现在该语句的缩进级别与任何以前的语句的缩进级别不匹配.例如,在下面的代码中,我们取消了第二次调用print.但是,缩进级别与任何前一个语句的级别不匹配:
>>> if True:
... if True:
... print('yes')
... print()
File "<stdin>", line 4
print()
^
IndentationError: unindent does not match any outer indentation level
Run Code Online (Sandbox Code Playgroud)
此错误尤其难以捕获,因为即使一个空格也会导致代码失败.
固定
修复是为了确保当您取消声明语句时,缩进级别与前一个语句的级别匹配.再次考虑上面的例子.在示例中,我希望第二次调用print在第一个if语句体中.所以我需要确保该行的缩进级别与第一个if语句的主体中的前一个语句的缩进级别相匹配:
>>> if True:
... if True:
... print('yes')
... print() # indentation level now matches former statement's level.
...
yes
>>>
Run Code Online (Sandbox Code Playgroud)
如果你的程序在视觉上看起来有正确的缩进,但你仍然得到一个IndentationError你很可能混合选项卡的空格.这有时会导致Python引发奇怪的错误.请参阅"TabError:缩进时标签和空格的不一致使用"是什么意思下的特殊情况?以便更深入地解释问题.
问题
仅当您尝试将制表符和空格混合为缩进字符时,才会出现此错误.如上所述,Python不允许您的程序包含选项卡和空格的混合,并且TabError如果它找到您将会引发特定的异常.例如,在下面的程序中,使用制表符和空格的混合来缩进:
>>> if True:
... if True:
... print()
... print()
... print()
File "<stdin>", line 5
print()
^
TabError: inconsistent use of tabs and spaces in indentation
Run Code Online (Sandbox Code Playgroud)
这是一张可视化显示上述程序中的空白的图片.灰点是空格,灰色箭头是标签:
我们可以看到我们确实混合了缩进的空格和制表符.
特别案例
注意如果将选项卡和空格混合到程序中,Python 将不会 总是引发TabError.如果程序缩进是明确的,Python将允许混合使用制表符和空格.例如:
>>> if True:
... if True: # tab
... pass # tab, then 4 spaces
...
>>>
Run Code Online (Sandbox Code Playgroud)
有时Python只会在制表符和空格的混合上窒息,并且在更合适IndentationError时TabError会错误地引发异常.另一个例子:
>>> if True:
... pass # tab
... pass # 4 spaces
File "<stdin>", line 3
pass # 4 spaces
^
IndentationError: unindent does not match any outer indentation level
Run Code Online (Sandbox Code Playgroud)
如您所见,以这种方式运行代码可能会产生神秘的错误.尽管程序在视觉上看起来很好,但是Python试图解析用于缩进和错误的选项卡和空格时感到困惑.
这些是很好的例子,它们演示了为什么在使用Python 2时永远不要混合制表符和空格并使用-t和-tt解释器标志.
固定
如果您的程序很短,可能最简单,最快捷的解决方法是简单地重新缩进程序.确保每个语句每个缩进级别缩进四个空格(请参阅如何缩进我的代码?).
但是,如果您已经有一个大型程序,您已将选项卡和空格混合在一起,则可以使用自动化工具将所有缩进转换为空格.
许多编辑器(如PyCharm和SublimeText)都可以选择自动将制表符转换为空格.还有一些在线工具,如Tabs To Spaces或Browserling,可以让您快速重新缩进代码.还有用Python编写的工具.例如,autopep8也可以自动重新缩进代码和其他缩进错误.
即使是最好的工具,有时也无法修复所有缩进错误,您必须手动修复它们.这就是为什么始终从一开始就正确缩进代码的重要性.
尽管不常见,SyntaxError但由于不正确的缩进,有时会引发某些异常.例如,看下面的代码:
if True:
pass
pass # oops! this statement should be indented!.
else:
pass
Run Code Online (Sandbox Code Playgroud)
运行上面的代码时,a SyntaxError is raised:
Traceback (most recent call last):
File "python", line 4
else:
^
SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
尽管Python引发了上述代码SyntaxError的真正问题,但是第二个pass语句应该缩进.因为第二个pass没有缩进,所以Python没有意识到前面的if语句和else语句是要连接的.
此类错误的修复方法是简单地正确重新缩进代码.要了解如何正确缩进代码,请参阅如何缩进代码部分?.
如果你还在苦苦挣扎,不要气馁.使用Python的空白语法规则可能需要一些时间.以下是一些有用的提示:
| 归档时间: |
|
| 查看次数: |
20016 次 |
| 最近记录: |