如何修复Pylint的“错误的悬挂缩进”和PEP8 E121?

33

我正试图正确地缩进以下代码片段:

RULES_LIST = [
    ('Name1', 1, 'Long string upto 40 chars'),
    ('Name2', 2, 'Long string upto 40 chars'),
    ('Name3', 3, 'Long string upto 40 chars'),
    ('Name4', 4, 'Long string upto 40 chars'),
    ('Name5', 5, 'Long string upto 40 chars'),
    ('Name6', 6, 'Long string upto 40 chars'),
    ('Name7', 7, 'Long string upto 40 chars'),
    ('Name8', 8, 'Long string upto 40 chars')
]

Pylint抱怨上述代码的缩进出现了错误,提示“Wrong hanging indentation.”。而PEP8则报告“E121: under-indented for hanging indent”。

可能的修复方法是将代码更改为:

RULES_LIST = [\
    ('Name1', 1, 'Long string upto 40 chars'),
     ...
    ('Name8', 8, 'Long string upto 40 chars')]

但是PEP8抱怨E121和E502

PEP8: 1.5.7 (默认配置)
Pylint: 1.3.0(默认配置)
Python: 2.7.5(运行在OSX 10.9.3上)

列表可能会变得更长。 请有人建议一个适当的缩进吗?


2
我刚刚在你的第一个示例上运行了默认配置的pylint和flake8,两者都没有问题。你是否使用了自定义的pylint配置?除了没有悬挂逗号之外,它看起来是正确的。 - Jason S
@JasonS:对我来说它显示了错误。我已经更新了问题,包括PEP8、Pylint和Python的配置和版本号。 - Jatin Kumar
只有在我将每行开头的4个空格替换为一个长度为4个空格的制表符时,才能重现此问题。使用空格时可以正常运行。如果您正在使用制表符,则可能需要将其替换为4个空格(或配置文本编辑器以针对Python文件执行此操作)。然而,pep8实际上告诉我存在制表符(并提供E121和不同的消息)。 - user707650
我只是在Pylint中禁用了这个消息。 “修复”源代码会使其变得不够健壮(插入''并确保之后没有任何空格),或者通过选择不再代表数据结构的缩进来降低可读性。 - BlackJack
请注意,pylint会向您显示被视为正确的位置(在源代码片段下面的行上的'^')。 - sthenault
pylint 1.4.4在默认配置下不会报错。 - jcomeau_ictx
4个回答

16

如果您想继续使用选项卡,您可以在 .pylintrc 文件中更改以下设置:

indent-string='\t'
indent-after-paren=1

如果你只改变第一个, pylint会期望使用四个制表符进行缩进。


12

你正在使用制表符而不是四个空格。

从pylint的角度来看,这三种可能性都是正确的,只要您使用四个空格而不是制表符,第一种是黑色将使用的方法:

RULES_LIST = [
    ('Name1', 1, 'Long string upto 40 chars'),
    ('Name2', 2, 'Long string upto 40 chars'),
    ('Name3', 3, 'Long string upto 40 chars'),
    ('Name4', 4, 'Long string upto 40 chars'),
    ('Name5', 5, 'Long string upto 40 chars'),
    ('Name6', 6, 'Long string upto 40 chars'),
    ('Name7', 7, 'Long string upto 40 chars'),
    ('Name8', 8, 'Long string upto 40 chars'),
]

RULES_LIST = [('Name1', 1, 'Long string upto 40 chars'),
              ('Name2', 2, 'Long string upto 40 chars'),
              ('Name3', 3, 'Long string upto 40 chars'),
              ('Name4', 4, 'Long string upto 40 chars'),
              ('Name5', 5, 'Long string upto 40 chars'),
              ('Name6', 6, 'Long string upto 40 chars'),
              ('Name7', 7, 'Long string upto 40 chars'),
              ('Name8', 8, 'Long string upto 40 chars')]

RULES_LIST = [
    ('Name1', 1, 'Long string upto 40 chars'),
    ('Name2', 2, 'Long string upto 40 chars'),
    ('Name3', 3, 'Long string upto 40 chars'),
    ('Name4', 4, 'Long string upto 40 chars'),
    ('Name5', 5, 'Long string upto 40 chars'),
    ('Name6', 6, 'Long string upto 40 chars'),
    ('Name7', 7, 'Long string upto 40 chars'),
    ('Name8', 8, 'Long string upto 40 chars')]

请注意,第一个中有一个尾随逗号,这是有意为之,因为它在添加行时减少了差异:

添加第9行时不带尾随逗号:

     ("Name7", 7, "Long string upto 40 chars"),
-    ("Name8", 8, "Long string upto 40 chars")
+    ("Name8", 8, "Long string upto 40 chars"),
+    ("Name9", 9, "Long string upto 40 chars")
 ]

添加第九行并以逗号结尾:

     ("Name8", 8, "Long string upto 40 chars"),
+    ("Name9", 9, "Long string upto 40 chars"),
 ]

感谢您提供所有的案例。这个问题困扰了我一段时间。 - zhihong
有没有一种工具可以自动将Python代码更改为像您的第三个示例那样的外观?(isort可以对导入执行此操作,但不能对其余代码执行此操作) - winklerrr
@winklerrr 如果存在的话,我从未听说过它,但是flake8可能会帮助您发现大多数问题。 - Julien Palard

0

我不想麻烦地去处理配置文件,所以我发现最简单的解决方案是在检查之前将制表符转换为空格:

expand --tabs=4 $filename | pylint --from-stdin stdin

注意:这需要pylint 2.4才能正常工作。请确保您仔细检查版本,因为当我将上面的行包装到自定义的pylint检查器脚本中时,它神秘地决定使用系统其他地方安装的不同版本的pylint,而不是终端给我的那个版本。
以下是一个大大简化的mylint脚本版本,您可以根据需要进行编辑:
set -e
pylint="/usr/bin/pylint"

#Warnings that I don't care about:
disabler(){
echo no-else-return             #No else after return
echo pointless-string-statement
echo no-self-use                #Class method without a self. in it.
echo useless-else-on-loop       #For else loop where the else isn't needed
echo too-many-locals            #More than 15 local vars
echo cell-var-from-loop         #https://dev59.com/Jl8e5IYBdhLWcg3w2NRR
echo no-else-continue           #No else after contiune statement
echo no-else-break              #No else after break statement
echo C0114,C0116                #Docstring nonsense

echo W0614,W0401                #Wildcard imports are fixed by star_namer.py
}

expand --tabs=4 $1 | $pylint --from-stdin stdin --max-line-length=120 --variable-rgx="[a-z0-9_]{1,30}$" --disable=`disabler | tr '\n' ','` --docstring-min-length=5 --min-public-methods=1  | sed G | less

能够轻松地注释、取消注释警告并留下一点注释,这真是太好了,这样我就不会忘记它们的作用。


-3

它期望可能是这样的

RULES_LIST = [
    ('Name1', 1, 'Long string upto 40 chars'),
    ('Name2', 2, 'Long string upto 40 chars'),
    ('Name3', 3, 'Long string upto 40 chars'),
    ('Name4', 4, 'Long string upto 40 chars'),
    ('Name5', 5, 'Long string upto 40 chars'),
    ('Name6', 6, 'Long string upto 40 chars'),
    ('Name7', 7, 'Long string upto 40 chars'),
    ('Name8', 8, 'Long string upto 40 chars')
    ]

闭合方括号。


你试过运行这个程序吗?它不起作用 :/ 就好像你在不使用“\”的情况下做任何事情,除非你将所有行(但第一行除外)缩进到开放方括号之外,否则它都不会起作用!! - Jatin Kumar
1
我认为这应该符合 pep8 的规范:“多行结构的闭合大括号/方括号/圆括号可以与列表最后一行的第一个非空白字符对齐”。然而,flake8 / pylint 仍会报错。 - FZeiser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接