Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером
Ошибки оформления — синтаксис и линтер
—
Основы Python
Если программа на Python написана синтаксически некорректно, то интерпретатор выводит на экран соответствующее сообщение. Также он указывает на файл и строчку, где произошла ошибка.
Синтаксическая ошибка возникает в том случае, когда код записали с нарушением грамматических правил. В естественных языках грамматика важна, но текст с ошибками обычно можно понять и прочитать. В программировании все строго. Мельчайшее нарушение — и программа даже не запустится. Примером может быть забытая ;
, неправильно расставленные скобки и другие детали.
Вот пример кода с синтаксической ошибкой:
print('Hodor)
Если запустить код выше, то мы увидим следующее сообщение:
$ python index.py
File "index.py", line 1
print('Hodor)
^
SyntaxError: EOL while scanning string literal
С одной стороны, ошибки синтаксиса — самые простые, потому что они связаны с грамматическими правилами написания кода, а не со смыслом кода. Их легко исправить: нужно лишь найти нарушение в записи. С другой стороны, интерпретатор не всегда может четко указать на это нарушение. Поэтому бывает, что забытую скобку нужно поставить не туда, куда указывает сообщение об ошибке.
Ошибки линтера
Мы уже научились писать простые программы, и поэтому можно немного поговорить о том, как писать их правильно.
Код нужно оформлять определенным образом, чтобы он был понятным и простым в поддержке. Существуют специальные наборы правил, которые описывают различные аспекты написания кода — их называют стандартами кодирования. В Python стандарт один — PEP8. Он отвечает практически на все вопросы о том, как оформлять ту или иную часть кода. Этот документ содержит все правила, которых нужно придерживаться. Новичкам мы советуем завести привычку заглядывать в стандарт PEP8 и писать код по нему.
Сегодня не нужно помнить все правила из стандарта, потому что существуют специальные программы, которые проверяют код автоматически и сообщают о нарушениях. Такие программы называются линтерами. Они проверяют код на соответствие стандартам. В Python их достаточно много, и наиболее популярный из них — flake8.
Взгляните на пример:
result = 1+ 3
Линтер будет ругаться на нарушение правила: E225 missing whitespace around operator. По стандарту, все операторы всегда должны отделяться пробелами от операндов.
Выше мы увидели правило E225 — это одно из большого количества правил. Другие правила описывают отступы, названия, скобки, математические операции, длину строчек и множество иных аспектов. Каждое отдельное правило кажется неважным и мелким, но вместе они составляют основу хорошего кода. Список всех правил flake8 доступен в этой документации.
Вы уже знакомы с линтером, потому что в практических заданиях платформа Хекслета проверяет ваш код с помощью него. Скоро вы начнете использовать его и за пределами Хекслета, когда будете реализовывать учебные проекты. Вы настроите линтер, и он будет проверять код уже в реальной разработке и сообщать вам о нарушениях.
Дополнительные материалы
- Как читать вывод тестов в Python
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты.
Your Vim plugin was wrong when you asked in 2013… but right in 2010, when it was authored. PEP 8 has changed on several occasions, and the answer to your question has changed as well.
Originally, PEP 8 contained the phrase:
Use spaces around arithmetic operators
Under that rule,
range(a, b+1)
is unambiguously wrong and should be written as
range(a, b + 1)
That is the rule that pycodestyle (the Python linter, previously known as pep8.py, that the asker’s Vim plugin uses under the hood) implemented for several years.
However, this was changed in April 2012. The straightforward language that left no room for discretion was replaced with this much woollier advice:
If operators with different priorities are used, consider adding whitespace around the operators with the lowest priority(ies). Use your own judgment; however, never use more than one space, and always have the same amount of whitespace on both sides of a binary operator.
Confusingly, the examples that illustrate this rule were originally left unchanged (and hence in contradiction to the prose). This was eventually fixed, but not very well, and the examples remain confusing, seeming to imply a much stricter and less subjective rule than the prose does.
There is still a rule requiring whitespace around some particular operators:
Always surround these binary operators with a single space on either side: assignment (
=
), augmented assignment (+=
,-=
etc.), comparisons (==
,<
,>
,!=
,<>
,<=
,>=
,in
,not in
,is
,is not
), Booleans (and
,or
,not
).
but note that this rule is explicit about which operators it refers to and arithmetic operators like +
are not in the list.
Thus the PEP, in its current form, does not dictate whether or not you should use spaces around the +
operator (or other arithmetic operators like *
and /
and **
). You are free to “use your own judgement”.
By the way, the pycodestyle linter changed its behaviour in late 2012 to reflect the change in the PEP, separating the rules about using whitespace around operators into two error codes, E225 (for failure to use whitespace around the operators that PEP 8 still requires whitespace around), which is on by default, and E226 (for failure to use whitespace around arithmetic operators), which is ignored by default. The question asker here must’ve been using a slightly outdated version of the linter when he asked this question in 2013, given the error that he saw.
Python’s PEP8 code specification, so record the common PEP8 code specification problems and solutions, learn it, and continue to update when you encounter it, develop good habits, and write standardized code!
PEP 8: no newline at end of file
Solution: You need to start a new line at the end of the code and move the cursor to the last carriage return
PEP 8: indentation is not a multiple of four
Solution: Indent is not a multiple of 4, check indent
PEP 8: over-indented
Solution: Excessive indentation, check indentation
PEP 8: missing whitespace after’,’
Solution: There are fewer spaces after the comma, just add spaces, similar to the semicolon or colon after the missing spaces
PEP 8: multiple imports on one line
Solution: Do not refer to multiple libraries in one sentence, for example:import socket, urllib.error
It is best written as:import socket
import urllib.error
PEP 8: blank line at end of line
Solution: There are more spaces at the end of the code, just delete the spaces
PEP 8: at least two spaces before inline comment
Solution: There must be at least two spaces between the code and the comment
PEP 8: block comment should start with ‘#’
Solution: The comment should start with # plus a space
PEP 8: inline comment should start with ‘#’
Solution: The comment should start with # plus a space
PEP 8: module level import not at top of file
Solution: import is not at the top of the file, there may be other code before
PEP 8: expected 2 blank lines,found 0
Solution: Two blank lines are needed, add two blank lines
PEP 8: function name should be lowercase
Solution: Change the function name to lower case
PEP 8: missing whitespace around operator
Solution: Operators (’=’, ‘>’, ‘<’, etc.) lack spaces before and after, just add
PEP 8: unexpected spaces around keyword / parameter equals
Solution: Unexpected spaces appear around the keyword / parameter equal sign, just remove the spaces
PEP 8: multiple statements on one line (colon)
Solution: The multi-line statement is written to one line, for example:if x == 2: print('OK')
Write in two lines
PEP 8: line too long (82 > 79 characters)
Solution: The maximum length limit of each line is exceeded 79
PEP 8: Simplify chained comparison
can simplify chain comparisons (for example:if a >= 0 and a <= 9:
Can be abbreviated as:if 0 <= a <= 9:
)
If you want to selectively ignore the warning message of the PEP8 code style, you can use the following methods: (Cultivate good habits and write standardized code! It is not recommended to ignore!)
①Move the mouse to the place where the warning message appears, pressalt+Enter, Choose to ignore (Ignore) this error:
②Select one by oneFile – Settings – Editor – Inspections, Found under PythonPEP8 coding style violation Options, in the lower right cornerIgnore errors Click the plus sign to add the warning message ID that needs to be ignored (see the appendix for ID information), for example, you want to ignoreindentation contains mixed spaces and tabs
For this warning, just add its ID:E101 Just
Appendix: All warning messages and corresponding IDs, official address: https://pep8.readthedocs.io/en/latest/intro.html#error-codes
code | sample message |
---|---|
E1 | Indentation |
E101 | indentation contains mixed spaces and tabs |
E111 | indentation is not a multiple of four |
E112 | expected an indented block |
E113 | unexpected indentation |
E114 | indentation is not a multiple of four (comment) |
E115 | expected an indented block (comment) |
E116 | unexpected indentation (comment) |
E117 | over-indented |
E121 (*^) | continuation line under-indented for hanging indent |
E122 (^) | continuation line missing indentation or outdented |
E123 (*) | closing bracket does not match indentation of opening bracket’s line |
E124 (^) | closing bracket does not match visual indentation |
E125 (^) | continuation line with same indent as next logical line |
E126 (*^) | continuation line over-indented for hanging indent |
E127 (^) | continuation line over-indented for visual indent |
E128 (^) | continuation line under-indented for visual indent |
E129 (^) | visually indented line with same indent as next logical line |
E131 (^) | continuation line unaligned for hanging indent |
E133 (*) | closing bracket is missing indentation |
E2 | Whitespace |
E201 | whitespace after ‘(‘ |
E202 | whitespace before ‘)’ |
E203 | whitespace before ‘:’ |
E211 | whitespace before ‘(‘ |
E221 | multiple spaces before operator |
E222 | multiple spaces after operator |
E223 | tab before operator |
E224 | tab after operator |
E225 | missing whitespace around operator |
E226 (*) | missing whitespace around arithmetic operator |
E227 | missing whitespace around bitwise or shift operator |
E228 | missing whitespace around modulo operator |
E231 | missing whitespace after ‘,’, ‘;’, or ‘:’ |
E241 (*) | multiple spaces after ‘,’ |
E242 (*) | tab after ‘,’ |
E251 | unexpected spaces around keyword / parameter equals |
E261 | at least two spaces before inline comment |
E262 | inline comment should start with ‘# ‘ |
E265 | block comment should start with ‘# ‘ |
E266 | too many leading ‘#’ for block comment |
E271 | multiple spaces after keyword |
E272 | multiple spaces before keyword |
E273 | tab after keyword |
E274 | tab before keyword |
E275 | missing whitespace after keyword |
E3 | Blank line |
E301 | expected 1 blank line, found 0 |
E302 | expected 2 blank lines, found 0 |
E303 | too many blank lines (3) |
E304 | blank lines found after function decorator |
E305 | expected 2 blank lines after end of function or class |
E306 | expected 1 blank line before a nested definition |
E4 | Import |
E401 | multiple imports on one line |
E402 | module level import not at top of file |
E5 | Line length |
E501 (^) | line too long (82 > 79 characters) |
E502 | the backslash is redundant between brackets |
E7 | Statement |
E701 | multiple statements on one line (colon) |
E702 | multiple statements on one line (semicolon) |
E703 | statement ends with a semicolon |
E704 (*) | multiple statements on one line (def) |
E711 (^) | comparison to None should be ‘if cond is None:’ |
E712 (^) | comparison to True should be ‘if cond is True:’ or ‘if cond:’ |
E713 | test for membership should be ‘not in’ |
E714 | test for object identity should be ‘is not’ |
E721 (^) | do not compare types, use ‘isinstance()’ |
E722 | do not use bare except, specify exception instead |
E731 | do not assign a lambda expression, use a def |
E741 | do not use variables named ‘l’, ‘O’, or ‘I’ |
E742 | do not define classes named ‘l’, ‘O’, or ‘I’ |
E743 | do not define functions named ‘l’, ‘O’, or ‘I’ |
E9 | Runtime |
E901 | SyntaxError or IndentationError |
E902 | IOError |
W1 | Indentation warning |
W191 | indentation contains tabs |
W2 | Whitespace warning |
W291 | trailing whitespace |
W292 | no newline at end of file |
W293 | blank line contains whitespace |
W3 | Blank line warning |
W391 | blank line at end of file |
W5 | Line break warning |
W503 (*) | line break before binary operator |
W504 (*) | line break after binary operator |
W505 (*^) | doc line too long (82 > 79 characters) |
W6 | Deprecation warning |
W601 | .has_key() is deprecated, use ‘in’ |
W602 | deprecated form of raising exception |
W603 | ‘<>’ is deprecated, use ‘!=’ |
W604 | backticks are deprecated, use ‘repr()’ |
W605 | invalid escape sequence ‘x’ |
W606 | ‘async’ and ‘await’ are reserved keywords starting with Python 3.7 |
Темные силы не дремлют. Они пробираются в дивное королевство Python и используют черную магию, чтобы осквернить главную реликвию — чистый код. Однако опасны не только злые чары.
Сегодня я расскажу о страшных чудовищах, которые, возможно, уже обжились в вашем коде и готовы устанавливать свои правила. Здесь нужен герой, который защитит безмятежный мир от злобных тварей. И именно вы станете тем, кто сразится с ними!
Всем героям, однако, нужно магическое снаряжение, которое верой и правдой послужит им в грандиозных битвах. К счастью, с нами будет линтер wemake-python-styleguide. Он станет тем самым острым оружием и надежным соратником.
Все готово, выступаем в поход!
Пожиратели пространства
А вот и первые проблемы. Жители стали замечать, как нечто лакомится пробелами, а операторы обретают причудливые формы:
x = 1
x -=- x
print(x)
# => 2
o = 2
o+=+o
print(o)
# => 4
print(3 --0-- 5 == 8)
# => True
Эти странные операторы состоят из совершенно обычных и дружественных нам -=
и -
. Посмотрим, сможет ли наш линтер найти их:
5:5 E225 missing whitespace around operator
x -=- x
^
5:5 WPS346 Found wrong operation sign
x -=- x
^
10:2 E225 missing whitespace around operator
o+=+o
^
14:10 E225 missing whitespace around operator
print(3 --0-- 5 == 8)
^
14:10 WPS346 Found wrong operation sign
print(3 --0-- 5 == 8)
^
14:11 WPS345 Found meaningless number operation
print(3 --0-- 5 == 8)
^
14:12 E226 missing whitespace around arithmetic operator
print(3 --0-- 5 == 8)
^
14:13 WPS346 Found wrong operation sign
print(3 --0-- 5 == 8)
^
Настала пора обнажить меч и принять бой:
x = 1
x += x
o = 2
o += o
print(3 + 5 == 8)
Враг повержен, и сразу вернулись прежние чистота и ясность!
Загадочные точки
Теперь жители сообщают о появлении странных глифов. О, смотрите-ка, вот и они!
print(0..__eq__(0))
# => True
print(....__eq__(((...))))
# => True
Что же здесь происходит? Кажется, там замешаны типы данных float
и Ellipsis
, но лучше удостовериться.
21:7 WPS609 Found direct magic attribute usage: __eq__
print(0..__eq__(0))
^
21:7 WPS304 Found partial float: 0.
print(0..__eq__(0))
^
24:7 WPS609 Found direct magic attribute usage: __eq__
print(....__eq__(((...))))
^
Ага, теперь понятно. Действительно, эти точки — краткая запись значений типа float
(в первом случае) и Ellipsis
(во втором). И в обоих случаях происходит обращение к методу, также через точку. Давайте посмотрим, что же скрывалось за этими знаками:
print(0.0 == 0)
print(... == ...)
На этот раз все обошлось, но впредь не сравнивайте константы друг с другом, дабы не накликать беду.
Кривая дорожка
А между тем у нас новая напасть — значения из некоторых веток в функции никогда не возвращаются. Давайте разберемся, в чем дело.
def some_func():
try:
return 'from_try'
finally:
return 'from_finally'
some_func()
# => 'from_finally'
Функция не возвращает значение 'from_try'
из-за закравшейся в код ошибки. «Как ее исправить?» — изумленно спросите вы.
31:5 WPS419 Found `try`/`else`/`finally` with multiple return paths
try:
^
Оказывается, wemake-python-styleguide
знает ответ: никогда не возвращайте значение из ветки finally
. Послушаемся совета.
def some_func():
try:
return 'from_try'
finally:
print('now in finally')
Мрачный СИ-луэт прошлого
Древнее существо пробуждается. Уже несколько десятилетий никто не видел его, но теперь оно вернулось.
a = [(0, 'Hello'), (1, 'world')]
for ['>']['>'>'>'], x in a:
print(x)
Что тут происходит? Известно, что в циклах можно распаковывать разные значения: почти любые валидные в Python выражения.
Правда, многое из этого примера нам не следовало бы делать:
44:1 WPS414 Found incorrect unpacking target
for ['>']['>'>'>'], x in a:
^
44:5 WPS405 Found wrong `for` loop variable definition
for ['>']['>'>'>'], x in a:
^
44:11 WPS308 Found constant compare
for ['>']['>'>'>'], x in a:
^
44:14 E225 missing whitespace around operator
for ['>']['>'>'>'], x in a:
^
44:21 WPS111 Found too short name: x
for ['>']['>'>'>'], x in a:
^
Теперь разберемся с ['>']['>'>'>']
. Похоже, что данное выражение можно просто переписать как ['>'][0]
, поскольку у выражения '>' > '>'
значение False
. А False
и 0
— одно и тоже.
Проблема решена.
Метки Темного Колдуна
Насколько сложным может быть выражение на Python? Наверняка такие конструкции — происки злых сил. Это Темный Колдун оставляет свои замысловатые метки во всех классах, к которым прикасается:
class _:
# Видите эти четыре метки?
_: [(),...,()] = {((),...,()): {(),...,()}}[((),...,())]
print(_._) # и этот оператор выглядит знакомо
# => {(), Ellipsis}
Что же за ними скрывается? Похоже, у каждой метки свое значение:
- Объявление и указание типа:
_: [(),...,()] =
. - Определение словаря, где значение — набор данных:
= { ((),...,()): {(),...,()} }
. - Ключ:
[((),...,())]
.
В мире людей подобная запись не имеет никакого смысла и безвредна, однако в королевстве Python она может стать оружием в злых руках. Давайте ее уберем:
55:5 WPS122 Found all unused variables definition: _
_: [(),...,()] = {((),...,()): {(),...,()}}[((),...,())]
^
55:5 WPS221 Found line with high Jones Complexity: 19
_: [(),...,()] = {((),...,()): {(),...,()}}[((),...,())]
^
55:36 WPS417 Found non-unique item in hash: ()
_: [(),...,()] = {((),...,()): {(),...,()}}[((),...,())]
^
57:7 WPS121 Found usage of a variable marked as unused: _
print(_._) # и этот оператор выглядит знакомо
^
Теперь, когда мы удалили или зарефакторили это выражение (со значением 19 по метрике сложности Jones Complexity), от метки Темного Колдуна в бедном классе не осталось и следа. Очередные ростки зла уничтожены.
Однако теперь наши классы связались с какими-то дурными типами, и те оказывают на них пагубное влияние.
Сейчас классы выдают очень странные результаты:
class Example(type((lambda: 0.)())):
...
print(Example(1) + Example(3))
# => 4.0
Почему 1 + 3
равно 4.0
, а не 4
? Чтобы это выяснить, рассмотрим поближе часть с type((lambda: 0.)())
:
(lambda: 0.)()
просто равно0.
, а это просто иная запись0.0
.type(0.0)
возвращает типfloat
.- когда мы пишем
Example(1)
, это значение преобразуется вExample(1.0)
внутри класса. Example(1.0) + Example(3.0) = Example(4.0)
.
Давайте убедимся, что наш линтер-клинок по-прежнему остр:
63:15 WPS606 Found incorrect base class
class Example(type((lambda: 0.)())):
^
63:21 WPS522 Found implicit primitive in a form of lambda
class Example(type((lambda: 0.)())):
^
63:29 WPS304 Found partial float: 0.
class Example(type((lambda: 0.)())):
^
64:5 WPS428 Found statement that has no effect
...
^
64:5 WPS604 Found incorrect node inside `class` body
...
^
Со всем разобрались, теперь наши классы в безопасности. Можем двигаться дальше.
Иллюзии
Иногда на пути встречаются выражения такие похожие, но такие разные. Вот и мы столкнулись с таким примером в коде. Выглядит, как самое обычное выражение-генератор, но на самом деле это кое-что совсем другое.
a = ['a', 'b']
print(set(x + '!' for x in a))
# => {'b!', 'a!'}
print(set((yield x + '!') for x in a))
# => {'b!', None, 'a!'}
Это одно из хтонических чудовищ Python — да, они все-таки существуют и тут. Учитывая, что в python3.8
такая конструкция приведет к SyntaxError
, yield
и yield from
следует использовать только в функциях-генераторах.
А вот и отчет об инциденте:
73:7 C401 Unnecessary generator - rewrite as a set comprehension.
print(set(x + '!' for x in a))
^
76:7 C401 Unnecessary generator - rewrite as a set comprehension.
print(set((yield x + '!') for x in a))
^
76:11 WPS416 Found `yield` inside comprehension
print(set((yield x + '!') for x in a))
И давайте перепишем обработку, как нам предлагают.
print({x + '!' for x in a})
Эта задачка была сложна, но и мы не лыком шиты. Что же дальше?
Злобный двойник email
Если нужно записать адрес электронной почты, то используем строку, ведь так? А вот и нет!
Для решения обычных задач существуют необычные способы. А у обычных типов данных есть злые двойники. Сейчас мы выясним, кто есть кто.
class G:
def __init__(self, s):
self.s = s
def __getattr__(self, t):
return G(self.s + '.' + str(t))
def __rmatmul__(self, other):
return other + '@' + self.s
username, example = 'username', G('example')
print(username@example.com)
# => username@example.com
Разберемся, как это работает.
- в Python
@
— это оператор, который можно переопределить с помощью магических методов__matmul__
и__rmatmul__
. - выражение
.com
означает обращение к свойствуcom
; переопределяется методом__getattr__
.
Этот пример значительно отличается от остальных тем, что он-то на самом деле корректный. Просто вот такой необычный. Вероятно, пользоваться им мы не будем, но в бестиарий запишем.
Сила заблуждений
В нашем королевстве настали смутные времена. Тьма наделила жителей сомнительными способностями. Это раскололо содружество разработчиков и привело к серьезным разногласиям.
Способности эти воистину страшные, ибо теперь вам дано программировать в строках:
from math import radians
for angle in range(360):
print(f'{angle=} {(th:=radians(angle))=:.3f}')
print(th)
# => angle=0 (th:=radians(angle))=0.000
# => 0.0
# => angle=1 (th:=radians(angle))=0.017
# => 0.017453292519943295
# => angle=2 (th:=radians(angle))=0.035
# => 0.03490658503988659
Что происходит в этом примере?
f'{angle=}
— это способ записиf'angle={angle}
в новых версиях (python3.8+).(th:=radians(angle))
— это операция присваивания значения; да, теперь можно так делать и внутри строки.=:.3f
указывает на формат вывода: возвращается значение, округленное до третьего знака- метод
print(th)
отрабатывает, так как(th:=radians(angle))
имеет локальную область видимости в части кода, где находится вся строка.
Стоит ли использовать f-строки? Как хотите.
Стоит ли определять переменные в f-строках? Ни в коем случае.
А вот дружеское напоминание о том, что еще можно (но, наверное, не нужно) написать с помощью f
-строк:
print(f"{getattr(__import__('os'), 'eman'[None:None:-1])}")
# => posix
Всего лишь импортируем модуль внутри строки, ничего такого, идем дальше.
К счастью, в реальном коде наше оружие сразу почует неладное и засветится, аки знаменитый меч Жало:
105:1 WPS221 Found line with high Jones Complexity: 16
print(f"{getattr(__import__('os'), 'eman'[None:None:-1])}")
^
105:7 WPS305 Found `f` string
print(f"{getattr(__import__('os'), 'eman'[None:None:-1])}")
^
105:18 WPS421 Found wrong function call: __import__
print(f"{getattr(__import__('os'), 'eman'[None:None:-1])}")
^
105:36 WPS349 Found redundant subscript slice
print(f"{getattr(__import__('os'), 'eman'[None:None:-1])}")
^
И еще кое-что: f
-строки нельзя использовать как переменные docstrings
:
def main():
f"""My name is {__file__}/{__name__}!"""
print(main().__doc__)
# => None
Заключение
Мы сразились со многими жуткими монстрами, расплодившимися в коде, и сделали королевство Python прекраснее. Вы герой, гордитесь собой!
Это было невероятное приключение. И я надеюсь, что вы узнали что-то новое для себя, что поможет в грядущих сражениях. Мир нуждается в вас!
На сегодня все. Удачи на тракте, пусть звезды ярко освещают ваш путь!
Полезные ссылки
- Python code disasters
- wtf, python?
- wemake-python-styleguide
А вы, вольные жители Python королевства, встречались с подобной черной магией в вашем коде? Удалось ли справиться с ней? Или битва еще не завершена (или вовсе проиграна)? Если вам нужна помощь бывалых магов и чародеев Python, то приходите к нам на Moscow Python Conf++ 27 марта 2020 года. У нас будут проверенные рецепты по борьбе с плохим и старым кодом от Владимира Филонова (доклад + 2 часа практики), Кирилла Борисова и Левона Авакяна.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Closed
moylop260 opened this issue
Sep 14, 2016
· 5 comments
· Fixed by #3577
Comments
Steps to reproduce
- Use the following code
var = 3+0
- Run
flake8 --show-source --select=E226 file.py
- See the outuput:
file.py:1:6: E226 missing whitespace around arithmetic operator
- Run
pylint -d invalid-name,missing-docstring file.py
Current behaviour
Not emit messages.
Expected behaviour
Should we emit the message of missing whitespace around operator
?
pylint –version output
pylint 1.6.4, astroid 1.4.8 Python 2.7.10 (default, Oct 23 2015, 19:19:21) [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)]
I agree that we should have a message for this.
I think we don’t have to mimic any flake8 or PEP 8 message for that matter, it would be an effort spent on things which are already handled quite well by other tools. I use pep8 in combination with pylint all the time, since I don’t expect pylint to follow PEP 8 to the heart. That is, if anyone is willing to provide the code for such a check, I would not mind adding in, but I don’t want to spend time on implementing it either.
We’re not going to merge new formatting check as black and other tools handle this better than pylint and we removed bad-whitespace
in #3577 and bad-continuation
in #3571.
It looks strange this bug is closed.
For those who came from google and want to enable such warning in vs code, I just switched to flake8 with such settings.json
:
{ "python.linting.enabled": true, "python.linting.flake8Enabled": true, "python.linting.flake8Args": [ ], }
And in panel I now can see the error I want:
I’d suggest using black
to autoformat your code, you don’t have to waste time adding a linter to warn about whitespaces around operator then also waste time by fixing them manually.