Python Coding Violations
Not In Loop
Description: Break or continue keywords are used outside a loop
def check_value(value):
if value > 10:
continue
print(value)
for i in range(3):
check_value(i)
for i in range(3):
if i == 2:
continue
print(i)
Function Redefined
Description: A function / class / method is redefined
def greet():
print('Hello')
def greet():
print('Hi again')
def say_hello():
print('Hello')
def say_goodbye():
print('Goodbye')
Continue In Finally
Description: Emitted when the continue
keyword is found inside a finally
clause, which is a SyntaxError
while running:
try:
pass
finally:
continue # [continue-in-finally]
while running:
try:
pass
except KeyError:
pass
else:
continue
Abstract Class Instantiated
Description: An abstract class with abc.ABCMeta
or abc.ABC
as metaclass has abstract methods and is instantiated
import abc
class Vehicle(abc.ABC):
@abc.abstractmethod
def start_engine(self):
pass
car = Vehicle() # [abstract-class-instantiated]
import abc
class Vehicle(abc.ABC):
@abc.abstractmethod
def start_engine(self):
pass
class Car(Vehicle):
def start_engine(self):
print("Vroom")
car = Car()
Star Needs Assignment Target
Description: Can use starred expression only in assignment target. Emitted when a star expression is not used in an assignment target
planets = *["Mercury", "Venus", "Earth"] # [star-needs-assignment-target]
mercury, *rest_of_planets = ["Mercury", "Venus", "Earth"]
Duplicate Argument Name
Description: Duplicate argument names in function definitions are syntax errors
def get_animals(dog, cat, dog): # [duplicate-argument-name]
pass
def get_animals(dog, cat, bird):
pass
Return In Init
Description: Explicit return in __init__
Used when the special class method __init__
has an explicit return value. __init__
magic method is a constructor of an instance, so it should construct it but not return anything.
class Multiply:
def __init__(self, x, y): # [return-in-init]
return x * y
class Multiply:
def __init__(self, x, y) -> None:
self.product = x * y
Too Many Star Expressions
Description: More than one starred expression in assignment. Emitted when there are more than one starred expressions (*x
) in an assignment. This is a SyntaxError
*dogs, *cats = ["Labrador", "Poodle", "Sphynx"] # [too-many-star-expressions]
*labrador_and_poodle, sphynx = ["Labrador", "Poodle", "Sphynx"]
Nonlocal And Global
Description: Emitted when a name is both nonlocal
and global
VALUE = 100
def update_value(new_value): # [nonlocal-and-global]
global VALUE
nonlocal VALUE
VALUE = new_value
print(f"Updated global value: {VALUE}")
update_value(200)
VALUE = 100
def update_value(new_value):
global VALUE
VALUE = new_value
print(f"Updated global value: {VALUE}")
update_value(200)
Used Prior Global Declaration
Description: Emitted when a name is used prior a global
declaration, which results in an error since Python 3.6. It can't be emitted when using Python < 3.6
FRUIT = "apple"
def update_fruit():
print(FRUIT) # [used-prior-global-declaration]
global FRUIT
FRUIT = "orange"
FRUIT = "apple"
def update_fruit():
global FRUIT
FRUIT = "banana"
Assignment Outside Function
Description: An assignment is found outside a function or method
x = 5 # [assignment-outside-function]
def assign_value():
x = 5
Return Arg In Generator
Description: A return
statement with an argument is found in a generator function or method. It's allowed in Python >= 3.3 but wasn't allowed earlier.
def yield_items():
for item in ['a', 'b', 'c']:
yield item
return "Finished!" # This was not allowed in Python 3.3 and earlier.
Invalid Star Assignment Target
Description: Starred assignment target must be in a list
or tuple
. Error occurs when using a star expression in invalid contexts.
*numbers = [1, 2, 3] # [invalid-star-assignment-target]
numbers = [1, 2, 3]
Bad Reversed Sequence
Description: The argument passed to reversed()
is not a sequence. This error occurs when a non-iterable type is passed to reversed()
.
reversed(1234) # [bad-reversed-sequence]
reversed([1, 2, 3, 4])
Nonexistent Operator
Description: Attempting to use C-style increment or decrement operators (++
or --
), which are not valid in Python.
x = 0
while x < 5:
print(x)
++x # [nonexistent-operator]
x = 0
while x < 5:
print(x)
x += 1
Yield Outside Function
Description: A yield
statement is found outside a function or method, which is invalid.
for i in range(5):
yield i # [yield-outside-function]
def range_yield():
for i in range(5):
yield i
Init Is Generator
Description: The special method __init__
is turned into a generator, which is incorrect. __init__
cannot contain yield
.
class Animal:
def __init__(self, names): # [init-is-generator]
yield from names
cat = Animal(["Tom", "Jerry"])
class Animal:
def __init__(self, names):
self.names = names
def get_names(self):
yield from self.names
cat = Animal(["Tom", "Jerry"])
for name in cat.get_names():
pass
Misplaced Format Function
Description: The format()
function is not called on a string object directly, causing an error.
print('Hello {}').format('World') # [misplaced-format-function]
print('Hello {}'.format('World'))
Nonlocal Without Binding
Description: Emitted when a nonlocal
variable does not have an attached name somewhere in the parent scopes
class Animal:
def get_sound(self):
nonlocal sounds # [nonlocal-without-binding]
class Animal:
sounds = ["bark", "meow"]
def get_sound(self):
nonlocal sounds
Lost Exception
Description: A break or a return statement is found inside the finally clause of a try
...finally
block, the exceptions raised in the try
clause will be silently swallowed instead of being re-raised
class InfinityError(ArithmeticError):
def __init__(self):
uper().__init__("You can't reach infinity!")
def calculate_division(dividend: float, divisor: float) -> float:
try:
return dividend / divisor
except ArithmeticError as e:
raise InfinityError() from e
finally:
return float('inf') # [lost-exception]
class InfinityError(ArithmeticError):
def __init__(self):
super().__init__("You can't reach infinity!")
def calculate_division(dividend: float, divisor: float) -> float:
try:
return dividend / divisor
except ArithmeticError as e:
raise InfinityError() from e
Assert On Tuple
Description: A call of assert
on a tuple
will always evaluate to true if the tuple
is not empty, and will always evaluate to false if it is
assert (42, None) # [assert-on-tuple]
val1, val2 = (42, None)
assert val1
assert val2
Assert On String Literal
Description: When an assert statement has a string literal as its first argument, which will cause the assert to always pass
def test_multiplication():
a = 4 * 5
assert "No MultiplicationError were raised" # [assert-on-string-literal]
def test_multiplication():
a = 4 * 5
assert a == 20
Self Assigning Variable
Description: Emitted when we detect that a variable is assigned to itself
temperature = 100
temperature = temperature # [self-assigning-variable]
temperature = 100
Comparison With Callable
Description: This message is emitted when pylint detects that a comparison with a callable was made, which might suggest that some parenthesis were omitted, resulting in potential unwanted behavior
def function_returning_a_number() -> int:
return 42
def is_forty_two(num: int = 21):
# 21 == <function function_returning_a_number at 0x7f343ff0a1f0>
return num == function_returning_a_number # [comparison-with-callable]
def function_returning_a_number() -> int:
return 42
def is_forty_two(num: int = 21):
# 21 == 42
return num == function_returning_a_number()
Dangerous Default Value
Description: A mutable value as list or dictionary is detected in a default value for an argument
def whats_in_the_bag(items=[]): # [dangerous-default-value]
items.append("book")
return items
def whats_in_the_bag(items=None):
if items is None:
items = []
items.append("book")
return items
Duplicate Key
Description: A dictionary expression binds the same key multiple times
exam_scores = {"English": 80, "Physics": 85, "English": 90} # [duplicate-key]
exam_scores = {"English": 80, "Physics": 85, "Chemistry": 90}
Useless Else On Loop
Description: Loops should only have an else clause if they can exit early with a break statement, otherwise the statements under else should be on the same scope as the loop itself
def find_positive_number(numbers):
for x in numbers:
if x > 0:
return x
else: # [useless-else-on-loop]
print("Did not find a positive number")
def find_positive_number(numbers):
for x in numbers:
if x > 0:
return x
print("Did not find a positive number")
Expression Not Assigned
Description: An expression that is not a function call is assigned to nothing. Probably something else was intended
float(3.14) == "3.14" # [expression-not-assigned]
is_equal: bool = float(3.14) == "3.14"
Confusing With Statement
Description: Emitted when a with
statement component returns multiple values and uses name binding with as
only for a part of those values, as in with ctx()
as a, b
. This can be misleading, since it's not clear if the context manager returns a tuple or if the node without a name binding is another context manager
with open("data.txt", "r") as f1, f2: # [confusing-with-statement]
pass
with open("data.txt", "r", encoding="utf8") as f1:
with open("log.txt", "w", encoding="utf8") as f2:
pass
Unnecessary Lambda
Description: The body of a lambda expression is a function call on the same argument list as the lambda itself. Such lambda expressions are in all but a few cases replaceable with the function being called in the body of the lambda
df.map(lambda x: x.upper()) # [unnecessary-lambda]
df.map(str.upper)
Assign To New Keyword
Description: async
and await
are reserved Python keywords in Python >= 3.6 versions
Redeclared Assigned Name
Description: Emitted when we detect that a variable was redeclared in the same assignment
ITEM, ITEM = ('apple', 'banana') # [redeclared-assigned-name]
ITEM1, ITEM2 = ('apple', 'banana')
Pointless Statement
Description: A statement doesn't have (or at least seems to) any effect
[4, 5, 6] # [pointless-statement]
NUMS = [4, 5, 6]
print(NUMS)
Pointless String Statement
Description: A string is used as a statement (which of course has no effect). This is a particular case of W0104 with its own message so you can easily disable it if you're using those strings as documentation, instead of comments
"""Function to calculate sum"""
"""Another pointless string statement""" # [pointless-string-statement]
"""Function to calculate sum"""
# A comment explaining the logic used in summing.
Unnecessary Pass
Description: A pass
statement that can be avoided is encountered
class ValidationError(Exception):
"""This exception is raised for invalid inputs."""
pass # [unnecessary-pass]
class ValidationError(Exception):
"""This exception is raised for invalid inputs."""
Unreachable
Description: There is some code behind a return
or raise
statement, which will never be accessed
def greet_user():
return True
print("Welcome!") # [unreachable]
def greet_user():
print("Welcome!")
return True
Eval Used
Description: You use the eval
function, to discourage its usage. Consider using ast.literal_eval
for safely evaluating strings containing Python expressions from untrusted sources
eval("{1: 'a', 2: 'b'}") # [eval-used]
from ast import literal_eval
literal_eval("{1: 'a', 2: 'b'}")
Exec Used
Description: You use the exec
statement (function for Python 3), to discourage its usage. That doesn't mean you cannot use it! It's dangerous to use this function for a user input
user_input = "John"
code = f"""eval(input('Execute this code, {user_input}: '))"""
result = exec(code) # [exec-used]
exec(result) # [exec-used]
def get_user_input(name):
return input(f"Enter code for execution, {name}: ")
user_input = "John"
allowed_globals = {"__builtins__": None}
allowed_locals = {"print": print}
# pylint: disable-next=exec-used
exec(get_user_input(user_input), allowed_globals, allowed_locals)
Using Constant Test
Description: Emitted when a conditional statement (If or ternary if) uses a constant value for its test
if False: # [using-constant-test]
print("Will never run.")
if True: # [using-constant-test]
print("Will always run.")
print("This statement is executed.")
Missing Parentheses For Call In Test
Description: Emitted when a conditional statement (If or ternary if) seems to wrongly call a function due to missing parentheses
import random
def is_sunny():
return random.choice([True, False])
if is_sunny: # [missing-parentheses-for-call-in-test]
print("It is sunny!")
import random
def is_sunny():
return random.choice([True, False])
if is_sunny():
print("It is sunny!")
Literal Comparison
Description: Comparing an object to a literal, which is usually what you do not want to do, since you can compare to a different literal than what was expected altogether
def is_a_banana(fruit):
return fruit is "banana" # [literal-comparison]
def is_a_banana(fruit):
return fruit == "banana"
Comparison With Itself
Description: Something is compared against itself
def is_a_banana(fruit):
a_banana = "banana"
return fruit == fruit # [comparison-with-itself]
def is_a_banana(fruit):
a_banana = "banana"
return a_banana == fruit
Non Ascii Name
Description: Name contains at least one non-ASCII unicode character
Invalid Name
Description: The name doesn't conform to naming rules associated to its type (constant, variable, class...)
class dog: # [invalid-name]
def Bark(self, NUMBER_OF_BARK): # [invalid-name, invalid-name]
print("Bark" * NUMBER_OF_BARK)
return NUMBER_OF_BARK
Dog = dog().Bark(10) # [invalid-name]
class Dog:
def bark(self, number_of_bark):
print("Bark" * number_of_bark)
return number_of_bark
DOG = Dog().bark(10)
Blacklisted Name
Description: The name is listed in the black list (unauthorized names)
Singleton Comparison
Description: An expression is compared to singleton values like True, False or None
lights_on = False
if lights_on == False: # [singleton-comparison]
print("Lights are off.")
lights_on = False
if not lights_on:
print("Lights are off.")
Misplaced Comparison Constant
Description: The constant is placed on the left side of a comparison. It is usually clearer in intent to place it in the right hand side of the comparison
Empty Docstring
Description: A module, function, class or method has an empty docstring (it would be too easy)
def bar(): # [empty-docstring]
""""""
def bar():
"""A simple function."""
Missing Class Docstring
Description: A class has no docstring. Even an empty class must have a docstring
class Car: # [missing-class-docstring]
def __init__(self, make, model):
self.make = make
self.model = model
class Car:
"""Class representing a car"""
def __init__(self, make, model):
self.make = make
self.model = model
Missing Function Docstring
Description: Missing function or method docstring used when a function or method has no docstring. Some special methods like __init__
, protected, private functions, setters and deleters do not require a docstring. It's a good practice to describe what a function does for other programmers
import os
def list_files(): # [missing-function-docstring]
print(os.listdir())
import os
def list_files():
"""Function listing files in the current directory."""
print(os.listdir())
Missing Module Docstring
Description: A module has no docstring. Empty modules do not require a docstring
import json # [missing-module-docstring]
def parse_json(data):
return json.loads(data)
"""Module providing a function for parsing JSON data."""
import json
def parse_json(data):
return json.loads(data)
Unidiomatic Typecheck
Description: Using type()
instead of isinstance()
for a type check. The idiomatic way to perform an explicit type check in Python is to use isinstance(x, y)
rather than type(x) == Y
, type(x) is Y
. Though there are unusual situations where these give different results
data = [1, 2, 3]
if type(data) is list: # [unidiomatic-typecheck]
pass
data = [1, 2, 3]
if isinstance(data, list):
pass
Access Member Before Definition
Description: An instance member is accessed before it's actually assigned
class Robot:
def __init__(self, power_level):
if self.power_level > 100: # [access-member-before-definition]
print("Power Overload!")
self.power_level = power_level
class Robot:
def __init__(self, power_level):
self.power_level = power_level
if self.power_level > 100:
print("Power Overload!")
Method Hidden
Description: A class defines a method which is hidden by an instance attribute from an ancestor class or set by some client code
class Plant:
def __init__(self, nutrients):
self.nutrients = nutrients
def nutrients(self): # [method-hidden]
pass
class Plant:
def __init__(self, nutrients):
self.nutrients = nutrients
def water_supply(self):
pass
Assigning Non Slot
Description: Assigning to an attribute not defined in the class slots
class Worker:
__slots__ = ("name")
def __init__(self, name, position):
self.name = name
self.position = position # [assigning-non-slot]
self.initialize()
class Worker:
__slots__ = ("name", "position")
def __init__(self, name, position):
self.name = name
self.position = position
self.initialize()
Duplicate Bases
Description: A class has duplicate bases
class Vehicle:
pass
class Bike(Vehicle, Vehicle): # [duplicate-bases]
pass
class Vehicle:
pass
class Bike(Vehicle):
pass
class Truck(Vehicle):
pass
Inconsistent Mro
Description: A class has an inconsistent method resolution order
class X:
pass
class Y(X):
pass
class Z(X, Y): # [inconsistent-mro]
pass
class X:
pass
class Y(X):
pass
class Z(Y): # or 'Y, X' but not 'X, Y'
pass
Inherit Non Class
Description: A class inherits from something which is not a class
class Animal(str): # [inherit-non-class]
pass
class Animal:
def __str__(self):
pass
Invalid Slots
Description: An invalid __slots__
is found in class. Only a string, an iterable or a sequence is permitted
class Vehicle: # [invalid-slots]
__slots__ = True
class Vehicle:
__slots__ = ("make", "model")
Invalid Slots Object
Description: An invalid (non-string) object occurs in __slots__
class Animal:
__slots__ = ("species", 5) # [invalid-slots-object]
class Animal:
__slots__ = ("species", "breed")
No Method Argument
Description: A method which should have the bound instance as first argument has no argument defined
class Dog:
def bark(): # [no-method-argument]
print("woof")
class Dog:
def bark(self):
print("woof")
No Self Argument
Description: A method has an attribute different the "self" as first argument. This is considered as an error since this is a so common convention that you shouldn't break it!
class Book:
def __init__(this, title): # [no-self-argument]
this.title = title
class Book:
def __init__(self, title):
self.title = title
Unexpected Special Method Signature
Description: Emitted when a special method was defined with an invalid number of parameters. If it has too few or too many, it might not work at all
class FileHandler:
def __enter__(self, filepath): # [unexpected-special-method-signature]
pass
def __exit__(self, exception): # [unexpected-special-method-signature]
pass
class FileHandler:
def __enter__(self):
pass
def __exit__(self, exc_type, exc_value, traceback):
pass
Class Variable Slots Conflict
Description: A value in slots conflicts with a class variable, property or method
class Robot:
# +1: [class-variable-slots-conflict]
__slots__ = ("model", "year", "shutdown")
model = None
def __init__(self, model, year):
self.model = model
self.year = year
@property
def year(self):
return self.year
def shutdown(self):
print("Shutting down...")
class Robot:
__slots__ = ("_year", "model")
def __init__(self, model, year):
self._year = year
self.model = model
@property
def year(self):
return self._year
def shutdown(self):
print("Shutting down...")
Invalid Bool Returned
Description: bool does not return bool Used when a bool method returns something which is not a bool
class LightSwitch:
"""__bool__ returns a string"""
def __bool__(self): # [invalid-bool-returned]
return "on"
Invalid Bytes Returned
Description: bytes does not return bytes Used when a bytes method returns something which is not bytes
class DataPacket:
"""__bytes__ returns <type 'list'>"""
def __bytes__(self): # [invalid-bytes-returned]
return [1, 2, 3]
class DataPacket:
"""__bytes__ returns <type 'bytes'>"""
def __bytes__(self):
return b"data"
Invalid Format Returned
Description: format does not return str Used when a format method returns something which is not a string
class Temperature:
"""__format__ returns <type 'float'>"""
def __format__(self, format_spec): # [invalid-format-returned]
return 98.6
class Temperature:
"""__format__ returns <type 'str'>"""
def __format__(self, format_spec):
return "98.6°F"
Invalid Getnewargs Returned
Description: getnewargs does not return a tuple. Used when a getnewargs method returns something which is not a tuple
class CustomGetNewArgs:
"""__getnewargs__ returns a string"""
def __getnewargs__(self): # [invalid-getnewargs-returned]
return 'abc'
class CustomGetNewArgs:
"""__getnewargs__ returns <type 'tuple'>"""
def __getnewargs__(self):
return ('abc', 'def')
Invalid Getnewargs Ex Returned
Description: getnewargs_ex does not return a tuple containing (tuple, dict). Used when a getnewargs_ex method returns something which is not of the form tuple(tuple, dict)
class CustomGetNewArgsEx:
"""__getnewargs_ex__ returns tuple with incorrect argument types"""
def __getnewargs_ex__(self): # [invalid-getnewargs-ex-returned]
return (list('x'), set())
class CustomGetNewArgsEx:
"""__getnewargs_ex__ returns <type 'tuple'>"""
def __getnewargs_ex__(self):
return ((1, 2), {'x': 'y'})
Invalid Hash Returned
Description: hash does not return an integer. Used when a hash method returns something which is not an integer
class CustomHash:
"""__hash__ returns a list"""
def __hash__(self): # [invalid-hash-returned]
return [1, 2, 3]
class CustomHash:
"""__hash__ returns an int"""
def __hash__(self):
return 123
Invalid Index Returned
Description: index does not return an integer. Used when an index method returns something which is not an integer
class CustomIndex:
"""__index__ returns a float"""
def __index__(self): # [invalid-index-returned]
return 3.14
class CustomIndex:
"""__index__ returns an int"""
def __index__(self):
return 42
Non Iterator Returned
Description: An __iter__
method returns something which is not an iterable (i.e., lacks a __next__
method)
import random
class RandomItems:
def __init__(self, items):
self.items = items
def __iter__(self): # [non-iterator-returned]
self.idx = 0
return self
LIST_ITEMS = ['Apple', 'Banana', 'Grape']
for item in RandomItems(LIST_ITEMS):
print(item)
import random
class RandomItems:
def __init__(self, items):
self.items = items
def __iter__(self):
self.idx = 0
return self
def __next__(self):
if self.idx == len(self.items):
raise StopIteration
self.idx += 1
return self.items[self.idx - 1]
LIST_ITEMS = ['Apple', 'Banana', 'Grape']
for item in RandomItems(LIST_ITEMS):
print(item)
Invalid Length Returned
Description: A __len__
method returns something that is not a non-negative integer
class CustomSet:
def __init__(self, elements):
self.elements = {'a', 'b', 'c'}
def __len__(self): # [invalid-length-returned]
return -1
class CustomSet:
def __init__(self, elements):
self.elements = {'a', 'b', 'c'}
def __len__(self):
return len(self.elements)
Invalid Length Hint Returned
Description: length_hint does not return a non-negative integer. Used when a length_hint method returns something that is not a non-negative integer
class CustomLengthHint:
"""__length_hint__ returns a negative int"""
def __length_hint__(self): # [invalid-length-hint-returned]
return -5
class CustomLengthHint:
"""__length_hint__ returns a non-negative int"""
def __length_hint__(self):
return 20
Invalid Repr Returned
Description: repr does not return str Used when a repr method returns something which is not a string
class CustomRepr:
"""__repr__ returns <type 'float'>"""
def __repr__(self): # [invalid-repr-returned]
return 3.14
class CustomRepr:
"""__repr__ returns <type 'str'>"""
def __repr__(self):
return "pi"
Invalid Str Returned
Description: str does not return str Used when a str method returns something which is not a string
class CustomStr:
"""__str__ returns list"""
def __str__(self): # [invalid-str-returned]
return [1, 2, 3]
class CustomStr:
"""__str__ returns <type 'str'>"""
def __str__(self):
return "apple pie"
Protected Access
Description: A protected member (i.e. class member with a name beginning with an underscore) is accessed outside the class or a descendant of the class where it's defined
class Bird:
def __fly(self):
pass
jane = Bird()
jane.__fly() # [protected-access]
class Bird:
def __fly(self):
pass
def soar(self):
return self.__fly()
jane = Bird()
jane.soar()
Attribute Defined Outside Init
Description: An instance attribute is defined outside the __init__
method
class Employee:
def promote(self):
self.is_promoted = True # [attribute-defined-outside-init]
class Employee:
def __init__(self):
self.is_promoted = False
def promote(self):
self.is_promoted = True
No Init
Description: A class has no __init__
method, neither its parent classes
class Car:
def drive(self):
print('driving')
class Car:
def __init__(self):
self.speed = 0
def drive(self):
print('driving')
Abstract Method
Description: An abstract method (i.e. raise NotImplementedError) is not overridden in concrete class
import abc
class Vehicle:
@abc.abstractmethod
def start_engine(self):
pass
class Bike(Vehicle): # [abstract-method]
pass
import abc
class Vehicle:
@abc.abstractmethod
def start_engine(self):
pass
class Bike(Vehicle):
def start_engine(self):
print("Vroom")
Invalid Overridden Method
Description: We detect that a method was overridden in a way that does not match its base class which could result in potential bugs at runtime
class Tree:
async def grow(self, soil):
soil.enrich(self)
class Oak(Tree):
def grow(self, soil): # [invalid-overridden-method]
soil.enrich(self)
class Tree:
async def grow(self, soil):
soil.enrich(self)
class Oak(Tree):
async def grow(self, soil):
soil.enrich(self)
Arguments Differ
Description: A method has a different number of arguments than in the implemented interface or in an overridden method
class Sandwich:
def make(self, bread, filling):
return f'{bread} and {filling}'
class BLTSandwich(Sandwich):
def make(self, bread, filling, bacon): # [arguments-differ]
return f'{bread}, {filling}, and {bacon}'
Signature Differs
Description: A method signature is different than in the implemented interface or in an overridden method
class Vehicle:
def start(self, fuel=100):
print(f"Started with {fuel} units of fuel!")
class Car(Vehicle):
def start(self, fuel): # [signature-differs]
super(Vehicle, self).start(fuel)
print("Engine is now running!")
class Vehicle:
def start(self, fuel=100):
print(f"Started with {fuel} units of fuel!")
class Car(Vehicle):
def start(self, fuel=100):
super(Vehicle, self).start(fuel)
print("Engine is now running!")
Bad Staticmethod Argument
Description: A static method has self
or a value specified in valid-classmethod-first-arg option or valid-metaclass-classmethod-first-arg option as the first argument
class Eagle:
@staticmethod
def fly(self): # [bad-staticmethod-argument]
pass
class Eagle:
@staticmethod
def fly(height):
pass
Useless Super Delegation
Description: Used whenever we can detect that an overridden method is useless, relying on super()
delegation to do the same thing as another method from the MRO
class Bird:
def fly(self):
print("Flying")
class Sparrow(Bird):
def fly(self): # [useless-super-delegation]
super().fly()
print("Flying again")
class Bird:
def fly(self):
print("Flying")
class Sparrow(Bird):
def fly(self):
print("Sparrow in flight")
Non Parent Init Called
Description: An __init__
method is called on a class which is not in the direct ancestors for the analysed class
class Insect:
def __init__(self):
self.has_wings = True
class Butterfly(Insect):
def __init__(self):
super().__init__()
self.is_beautiful = True
class MonarchButterfly(Butterfly):
def __init__(self):
Insect.__init__(self) # [non-parent-init-called]
self.is_migratory = True
class Insect:
def __init__(self):
self.has_wings = True
class Butterfly(Insect):
def __init__(self):
super().__init__()
self.is_beautiful = True
class MonarchButterfly(Butterfly):
def __init__(self):
super().__init__()
self.is_migratory = True
Super Init Not Called
Description: An ancestor class method has an __init__
method which is not called by a derived class
class Tree:
def __init__(self, species="Tree"):
self.species = species
print(f"Planting a {self.species}")
class Oak(Tree):
def __init__(self): # [super-init-not-called]
print("Growing an oak tree")
class Tree:
def __init__(self, species="Tree"):
self.species = species
print(f"Planting a {self.species}")
class Oak(Tree):
def __init__(self):
super().__init__("Oak")
Property With Parameters
Description: Detected that a property also has parameters, which are useless, given that properties cannot be called with additional arguments
class Drill:
@property
def depth(self, value): # [property-with-parameters]
pass
class Drill:
@property
def depth(self):
"""Property accessed with '.depth'."""
pass
def set_depth(value):
"""Function called with .set_depth(value)."""
pass
Useless Object Inheritance
Description: A class inherits from object
, which under Python 3 is implicit, hence can be safely removed from bases
class Plane(object): # [useless-object-inheritance]
...
class Plane: ...
No Classmethod Decorator
Description: A class method is defined without using the decorator syntax
class Flower:
COLORS = []
def __init__(self, color):
self.color = color
def set_colors(cls, *args):
"""classmethod to set flower colors"""
cls.COLORS = args
set_colors = classmethod(set_colors) # [no-classmethod-decorator]
class Flower:
COLORS = []
def __init__(self, color):
self.color = color
@classmethod
def set_colors(cls, *args):
"""classmethod to set flower colors"""
cls.COLORS = args
No Staticmethod Decorator
Description: A static method is defined without using the decorator syntax
class Mouse:
def run(self):
pass
run = staticmethod(run) # [no-staticmethod-decorator]
class Mouse:
@staticmethod
def run(self):
pass
No Self Use
Description: A method doesn't use its bound instance, and so could be written as a function
class Car:
def start_engine(self): # [no-self-use]
print('Engine started')
def start_engine():
print('Engine started')
Single String Used For Slots
Description: A class __slots__
is a simple string, rather than an iterable
class Tree: # [single-string-used-for-slots]
__slots__ = 'species'
def __init__(self, species):
self.species = species
class Tree:
__slots__ = ('species',)
def __init__(self, species):
self.species = species
Bad Classmethod Argument
Description: A class method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to "cls"), recommended to easily differentiate them from regular instance methods
class Vehicle:
@classmethod
def create(cls): # [bad-classmethod-argument]
return cls()
class Vehicle:
@classmethod
def create(cls):
return cls()
Bad Mcs Classmethod Argument
Description: A metaclass class method has a first argument named differently than the value specified in valid-metaclass-classmethod-first-arg option (default to mcs
), recommended to easily differentiate them from regular instance methods
class Factory(type):
@classmethod
def make_product(thing): # [bad-mcs-classmethod-argument]
pass
class Factory(type):
@classmethod
def make_product(mcs):
pass
Bad Mcs Method Argument
Description: A metaclass method has a first argument named differently than the value specified in valid-classmethod-first-arg option (default to cls
), recommended to easily differentiate them from regular instance methods
class Manager(type):
def assign_task(task): # [bad-mcs-method-argument]
pass
class Manager(type):
def assign_task(cls):
pass
Method Check Failed
Description: Pylint has been unable to check methods signature compatibility for an unexpected reason. Please report this kind if you don't make sense of it
class Device:
def start_device(self, config):
# [method-check-failed]
pass
class Device:
def start_device(self, config):
pass
Too Few Public Methods
Description: Class has too few public methods, so be sure it's really worth it
class Bird:
def __init__(self, species: str):
self.species = species
def fly(self):
print(f"The {self.species} is flying.")
import dataclasses
@dataclasses.dataclass
class Bird:
species: str
def fly(bird: Bird):
print(f"The {bird.species} is flying.")
Too Many Ancestors
Description: Class has too many parent classes, try to reduce this to get a simpler (and so easier to use) class
class Mammal: ...
class FlyingAnimal(Mammal): ...
class SwimmingAnimal(Mammal): ...
class EndangeredSpecies(Mammal): ...
# max of 7 by default, can be configured
class Bat( # [too-many-ancestors]
FlyingAnimal,
SwimmingAnimal,
EndangeredSpecies,
):
pass
class Animal:
can_fly: bool
can_swim: bool
is_endangered: bool
class Mammal(Animal):
can_fly = False
can_swim = False
is_endangered = False
class Bat(Mammal):
can_fly = True
is_endangered = True
Too Many Arguments
Description: A function or method takes too many arguments
def process_sensor_data( # [too-many-arguments]
accelerometer,
gyroscope,
magnetometer,
barometer,
proximity_sensor,
light_sensor,
current_time,
temperature_sensor,
):
pass
from dataclasses import dataclass
@dataclass
class Sensor:
accelerometer: float
gyroscope: float
magnetometer: float
barometer: float
@dataclass
class EnvironmentSensor:
proximity: float
light: float
temperature: float
def process_sensor_data(
motion: Sensor,
environment: EnvironmentSensor,
current_time,
):
pass
Too Many Boolean Expressions
Description: An if statement contains too many boolean expressions
def check_valid_triangle(a, b, c):
# +1: [too-many-boolean-expressions]
if (a > 0 and b > 0 and c > 0) and (a + b > c and a + c > b and b + c > a):
pass
def check_valid_triangle(a, b, c):
if all(x > 0 for x in [a, b, c]) and (a + b > c and a + c > b and b + c > a):
pass
Too Many Branches
Description: A function or method has too many branches, making it hard to follow
def map_day_to_word(day): # [too-many-branches]
if day == 1:
return 'Monday'
elif day == 2:
return 'Tuesday'
elif day == 3:
return 'Wednesday'
elif day == 4:
return 'Thursday'
elif day == 5:
return 'Friday'
elif day == 6:
return 'Saturday'
elif day == 7:
return 'Sunday'
else:
return None
def map_day_to_word(day):
return {
1: 'Monday',
2: 'Tuesday',
3: 'Wednesday',
4: 'Thursday',
5: 'Friday',
6: 'Saturday',
7: 'Sunday',
}.get(day)
Too Many Instance Attributes
Description: Class has too many instance attributes, try to reduce this to get a simpler (and so easier to use) class
class Car: # [too-many-instance-attributes]
def __init__(self):
self.make = 'Toyota'
self.model = 'Camry'
self.year = 2022
self.engine = 'V6'
self.transmission = 'Automatic'
self.color = 'Blue'
self.fuel_type = 'Gasoline'
self.seating_capacity = 5
self.mileage = 30000
import dataclasses
@dataclasses.dataclass
class Engine:
engine_type: str
fuel_type: str
@dataclasses.dataclass
class Car:
make: str
model: str
year: int
engine: Engine
seating_capacity: int
mileage: int
car = Car(
make='Toyota', model='Camry', year=2022, engine=Engine('V6', 'Gasoline'), seating_capacity=5, mileage=30000
)
Too Many Locals
Description: A function or method has too many local variables
def process_purchase_info(purchases): # [too-many-locals]
item_list = []
purchase_total = 0
discount = 0.1
shipping_cost = 5.99
tax = 0.07
final_total = 0
reward_points = 0
loyalty_bonus = 0.05
payment_method = 'Credit Card'
for item in purchases:
pass
from typing import NamedTuple
class PurchaseDetails(NamedTuple):
purchase_total: float
discount: float
shipping_cost: float
tax: float
def process_purchase_info(purchases):
purchase_details = PurchaseDetails(100, 0.1, 5.99, 0.07)
final_total = _calculate_final_total(purchase_details)
_handle_rewards_and_loyalty(purchases, final_total)
def _calculate_final_total(details: PurchaseDetails):
# logic to calculate final total
pass
def _handle_rewards_and_loyalty(purchases, final_total):
# handle reward logic
pass
Too Many Public Methods
Description: Class has too many public methods, try to reduce this to get a simpler (and so easier to use) class
class Game: # [too-many-public-methods]
def start(self): pass
def stop(self): pass
def reset(self): pass
def save(self): pass
def load(self): pass
def pause(self): pass
def resume(self): pass
def quit(self): pass
def restart(self): pass
def autosave(self): pass
class GameController:
def __init__(self):
self.state = 'Stopped'
def start(self):
self.state = 'Running'
def stop(self):
self.state = 'Stopped'
def pause(self):
self.state = 'Paused'
class SaveSystem:
def save(self): pass
def load(self): pass
class Game:
def __init__(self):
self.controller = GameController()
self.save_system = SaveSystem()
Too Many Return Statements
Description: Function contains too many return statements
def classify_grade(score):
if score >= 90:
return 'A'
elif score >= 80:
return 'B'
elif score >= 70:
return 'C'
elif score >= 60:
return 'D'
else:
return 'F'
def classify_grade(score):
return next((grade for score_threshold, grade in [(90, 'A'), (80, 'B'), (70, 'C'), (60, 'D')] if score >= score_threshold), 'F')
Too Many Statements
Description: A function or method contains too many statements
def initialize_game(): # [too-many-statements]
player = Player()
game = Game()
game.setup_board()
game.assign_pieces()
player.set_position(0, 0)
player.set_health(100)
player.set_inventory([])
enemy = Enemy()
enemy.set_position(10, 10)
enemy.set_health(100)
weapon = Weapon('sword')
armor = Armor('shield')
player.equip(weapon)
player.equip(armor)
game.start()
def initialize_game():
player = _initialize_player()
enemy = _initialize_enemy()
game = _initialize_game_environment(player, enemy)
game.start()
def _initialize_player():
player = Player()
player.set_position(0, 0)
player.set_health(100)
player.set_inventory([])
player.equip(Weapon('sword'))
player.equip(Armor('shield'))
return player
def _initialize_enemy():
enemy = Enemy()
enemy.set_position(10, 10)
enemy.set_health(100)
return enemy
def _initialize_game_environment(player, enemy):
game = Game()
game.setup_board()
game.assign_pieces()
return game
Bad Except Order
Description: Except clauses are not in the correct order (from the more specific to the more generic). If you don't fix the order, some exceptions may not be caught by the most specific handler.
try:
result = int(input('Enter a number: '))
except Exception:
print('An error occurred')
except ValueError: # [bad-except-order]
print('Invalid input')
try:
result = int(input('Enter a number: '))
except ValueError:
print('Invalid input')
except Exception:
print('An error occurred')
Catching Non Exception
Description: A class which doesn't inherit from Exception
is used as an exception in an except clause
class BarError:
pass
try:
'abc' + 123
except BarError: # [catching-non-exception]
pass
class BarError(Exception):
pass
try:
'abc' + 123
except BarError:
pass
Bad Exception Context
Description: Using the syntax raise ... from ...
, where the exception context is not an exception, nor None. This message belongs to the exceptions checker
try:
raise ValueError('Issue encountered') from 'Not an exception' # [bad-exception-context]
except ValueError:
pass
try:
raise ValueError('Issue encountered') from KeyError('Wrong key')
except ValueError:
pass
Notimplemented Raised
Description: NotImplemented
is raised instead of NotImplementedError
class Bird:
def fly(self):
raise NotImplemented # [notimplemented-raised]
class Bird:
def fly(self):
raise NotImplementedError
Raising Bad Type
Description: Something which is neither a class, an instance or a string is raised (i.e. a TypeError
will be raised)
class ImpossibleCalculationError(OverflowError):
def __init__(self):
super().__init__("Calculation exceeded the limits!")
def calculate_area(radius: float) -> float:
try:
return 3.14 * radius ** 2
except OverflowError as e:
raise None # [raising-bad-type]
class ImpossibleCalculationError(OverflowError):
def __init__(self):
super().__init__("Calculation exceeded the limits!")
def calculate_area(radius: float) -> float:
try:
return 3.14 * radius ** 2
except OverflowError as e:
raise ImpossibleCalculationError() from e
Raising Non Exception
Description: A new style class which doesn't inherit from BaseException
is raised
raise list # [raising-non-exception]
raise ValueError("Invalid operation!")
Misplaced Bare Raise
Description: A bare raise is not used inside an except clause. This generates an error, since there are no active exceptions to be reraised. An exception to this rule is represented by a bare raise inside a finally clause, which might work, as long as an exception is raised inside the try block, but it is nevertheless a code smell that must not be relied upon
def validate_input(x):
if x == '':
raise # [misplaced-bare-raise]
def validate_input(x):
if x == '':
raise ValueError(f"Input cannot be empty: {x}")
Duplicate Except
Description: An except catches a type that was already caught by a previous handler
try:
1 + 'a'
except TypeError:
pass
except TypeError: # [duplicate-except]
pass
try:
1 + 'a'
except TypeError:
pass
Broad Except
Description: An except catches a too general exception, possibly burying unrelated errors
try:
1 / 0
except Exception: # [broad-except]
pass
try:
1 / 0
except ZeroDivisionError: # handle specific error
pass
Raise Missing From
Description: Consider explicitly re-raising using the 'from' keyword. Python 3's exception chaining ensures the traceback shows both the current exception and the original one. Not using 'raise from' leads to an inaccurate traceback that might obscure the true source of the error.
try:
open('non_existent_file.txt')
except FileNotFoundError as e:
raise IOError("File cannot be opened") # [raise-missing-from]
try:
open('non_existent_file.txt')
except FileNotFoundError as e:
raise IOError("File cannot be opened") from e
Raising Format Tuple
Description: Passing multiple arguments to an exception constructor, with one of them being a tuple for string formatting, leads to incorrect behavior. Correct the formatting by using '%' operator inside the string.
raise TypeError("Unsupported operand type(s) %s %s", ("int", "str")) # [raising-format-tuple]
raise TypeError("Unsupported operand type(s) %s %s" % ("int", "str"))
Binary Op Exception
Description: Avoid using except A or B
for catching exceptions. To catch multiple exceptions, use the tuple syntax: except (A, B)
.
try:
int('abc')
except ValueError or TypeError: # [binary-op-exception]
pass
try:
int('abc')
except (ValueError, TypeError):
pass
Wrong Exception Operation
Description: Binary operations between exceptions like ValueError + TypeError
are invalid. Use a tuple (ValueError, TypeError)
to catch multiple exceptions.
try:
float('abc')
except ValueError + TypeError: # [wrong-exception-operation]
pass
try:
float('abc')
except (ValueError, TypeError):
pass
Bare Except
Description: Avoid using bare except
clauses, as they catch all exceptions and obscure the specific errors you're trying to handle.
try:
open('non_existent_file.txt')
except: # [bare-except]
file = None
try:
open('non_existent_file.txt')
except FileNotFoundError:
file = None
Try Except Raise
Description: Raising the same exception immediately after catching it (raise
by itself) is redundant. Either raise a more detailed exception or remove the try-except block entirely.
try:
int('invalid')
except ValueError as e: # [try-except-raise]
raise
# Raise a more descriptive exception:
try:
int('invalid')
except ValueError as e:
raise TypeError("Input must be a valid integer") from e
Bad Indentation
Description: Improper indentation in Python is problematic, as it can lead to runtime errors. Ensure consistent indentation.
if input():
print('yes') # [bad-indentation]
if input():
print('yes')
Missing Final Newline
Description: The last line in a file is missing a newline
open("file.txt") # CRLF
close("file.txt") # End-of-file (EOF)
# [missing-final-newline]
open("file.txt")
close("file.txt")
# End-of-file (EOF)
Line Too Long
Description: A line is longer than a given number of characters
# +1: [line-too-long]
PLANETS = ["mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune"]
PLANETS = [
"mercury",
"venus",
"earth",
"mars",
"jupiter",
"saturn",
"uranus",
"neptune",
]
Mixed Line Endings
Description: There are mixed (LF and CRLF) newline signs in a file
read_file("file.txt") # CRLF
write_file("file.txt") # LF
# [mixed-line-endings]
read_file("file.txt") # CRLF
write_file("file.txt") # CRLF
Multiple Statements
Description: More than one statement is found on the same line
animals = ["cat", "dog", "parrot"]
if "cat" in animals: pass # [multiple-statements]
else:
print("no cats!")
animals = ["cat", "dog", "parrot"]
if "cat" in animals:
pass
else:
print("no cats!")
Too Many Lines
Description: A module has too many lines, reducing its readability
def calculate_sum(lst): # [too-many-lines]
sum = 0
for num in lst:
sum += num
return sum
def main():
print(calculate_sum([1, 2, 3]))
print(calculate_sum([10, 20, 30]))
Trailing Newlines
Description: There are trailing blank lines in a file
print("banana")
# The file ends with 2 empty lines # +1: [trailing-newlines]
print("banana")
Trailing Whitespace
Description: There is whitespace between the end of a line and the newline
print("Goodbye")
# [trailing-whitespace] #
print("Goodbye")
Unexpected Line Ending Format
Description: There is a different newline than expected
print("I'm eating breakfast!") # CRLF
print("I'm eating lunch!") # CRLF
# [unexpected-line-ending-format]
print("I'm eating breakfast!") # LF
print("I'm eating lunch!") # LF
Superfluous Parens
Description: A single item in parentheses follows an if
, for
, or other keyword
name = input()
age = input()
if (name == age): # [superfluous-parens]
pass
name = input()
age = input()
if name == age:
pass
Relative Beyond Top Level
Description: A relative import tries to access too many levels in the current package
from ................galaxy import Star # [relative-beyond-top-level]
from universe.galaxy import Star
Import Self
Description: A module is importing itself
from my_module import function_name # [import-self]
def function_name():
pass
Preferred Module
Description: A module imported has a preferred replacement module. They are configured in .pylintrc
or through CLI arguments
import xmlrpc.client # [preferred-module]
import http.client
Reimported
Description: A module is reimported multiple times
import json
import json # [reimported]
import json
Deprecated Module
Description: Used a module marked as deprecated is imported
import imp # [deprecated-module]
import importlib
Wildcard Import
Description: This is a bad practice because it clutters namespace with unneeded modules, packages, variables, etc. Moreover, it takes time to load them too
from os import * # [wildcard-import]
import os
from os.path import join, dirname
Misplaced Future
Description: Python 2.5 and greater require future import to be the first non-docstring statement in the module. This message belongs to the imports checker
import time
from __future__ import division # [misplaced-future]
from __future__ import division
import time
Cyclic Import
Description: A cyclic import between two or more modules is detected
def add_numbers():
from .helper import add_two_numbers
return add_two_numbers() + 1
def add_two_numbers():
return 2
def add_three_numbers():
return add_two_numbers() + 1
Wrong Import Order
Description: PEP8 import order is not respected (standard imports first, then third-party libraries, then local imports)
import os
from . import tools
import sys # [wrong-import-order]
import os
import sys
from . import tools
Wrong Import Position
Description: Code and imports are mixed
import os
user_dir = os.getenv('USER')
import sys # [wrong-import-position]
import os
import sys
user_dir = os.getenv('USER')
Useless Import Alias
Description: An import alias is the same as the original package (e.g., using import numpy as numpy
instead of import numpy as np
)
import numpy as numpy # [useless-import-alias]
import numpy as np
Import Outside Toplevel
Description: An import statement is used anywhere other than the module top-level. Move this import to the top of the file
def get_version():
import platform
return platform.python_version()
import platform
def get_version():
return platform.python_version()
Ungrouped Imports
Description: Imports are not grouped by packages
import os
import sys
import json
import logging.config # [ungrouped-imports]
import os
import sys
import logging.config
import json
Multiple Imports
Description: Import statement importing multiple modules is detected
import os, sys # [multiple-imports]
import os
import sys
Logging Format Truncated
Description: A logging statement format string terminates before the end of a conversion specifier
import logging
logging.warning("Incorrect version: %", sys.version) # [logging-format-truncated]
import logging
logging.warning("Python version: %s", sys.version)
Logging Too Few Args
Description: A logging format string is given too few arguments
import logging
try:
function()
except Exception as e:
logging.error("%s error: %s", e) # [logging-too-few-args]
import logging
try:
function()
except Exception as e:
logging.error("%s error: %s", type(e), e)
Logging Too Many Args
Description: A logging format string is given too many arguments
import logging
try:
function()
except Exception as e:
logging.error("Error: %s", type(e), e) # [logging-too-many-args]
import logging
try:
function()
except Exception as e:
logging.error("%s error: %s", type(e), e)
Logging Unsupported Format
Description: An unsupported format character is used in a logging statement format string
import logging
logging.info("%s %y", "Hello", "World") # [logging-unsupported-format]
import logging
logging.info("%s %s", "Hello", "World")
Logging Format Interpolation
Description: A logging statement uses a call form of logging.<logging method>(format_string.format(...))
. It’s better to pass the parameters directly to the logging function instead
logging.error("Version: {}".format(sys.version)) # [logging-format-interpolation]
logging.error("Version: %s", sys.version)
Logging Fstring Interpolation
Description: A logging statement has a call form of logging.<logging method>(f"...")
. Use another type of string formatting instead. You can use different formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-format-interpolation is disabled then you can use str.format. If logging-not-lazy is disabled then you can use certain formatting as normal
import logging
import os
logging.warning(f"Current directory: {os.getcwd()}") # [logging-fstring-interpolation]
import logging
import os
logging.warning("Current directory: %s", os.getcwd())
Logging Not Lazy
Description: A logging statement has a call form of logging.<logging method>(format_string % (format_args...))
. Use another type of string formatting instead. You can use different formatting but leave interpolation to the logging function by passing the parameters as arguments. If logging-fstring-interpolation is disabled then you can use fstring formatting. If logging-format-interpolation is disabled then you can use str.format
import logging
try:
connect_to_database()
except DatabaseError as e:
logging.error("Database connection failed: %s" % e) # [logging-not-lazy]
raise
import logging
try:
connect_to_database()
except DatabaseError as e:
logging.error("Database connection failed: %s", e)
raise
Unpacking In Except
Description: Implicit unpacking of exceptions is not supported in Python 3 Python3 will not allow implicit unpacking of exceptions in except clauses. See https://www.python.org/dev/peps/pep-3110/
try:
raise ValueError("An error occurred")
except ValueError, e: # Implicit unpacking (invalid in Python 3)
print(e)
try:
raise ValueError("An error occurred")
except ValueError as e: # Explicit unpacking (valid in Python 3)
print(e)
Import Star Module Level
Description: Import * only allowed at module level Used when the import star syntax is used somewhere else than the module level. This message can't be emitted when using Python >= 3.0
def my_function():
from math import * # Importing * inside a function (invalid)
from math import * # Importing * at the module level (valid)
Non Ascii Bytes Literal
Description: Non-ascii bytes literals not supported in 3.x Used when non-ascii bytes literals are found in a program. They are no longer supported in Python 3. This message can't be emitted when using Python >= 3.0
my_bytes = b"non-ASCII character: ü" # Non-ASCII byte literal (invalid in Python 3)
my_string = "non-ASCII character: ü" # Use string literals for non-ASCII text
Parameter Unpacking
Description: Parameter unpacking specified Used when parameter unpacking is specified for a function(Python 3 doesn't allow it)
exec 'print("Hello, world!")' # Python 2 style exec statement (invalid in Python 3)
exec('print("Hello, world!")') # Use exec() function in Python 3
Long Suffix
Description: Use of long suffix Used when "l" or "L" is used to mark a long integer. This will not work in Python 3, since int and long types have merged. This message can't be emitted when using Python >= 3.0
my_number = long(100) # long is not available in Python 3 (invalid)
my_number = int(100) # Use int in Python 3
Old Octal Literal
Description: Use of old octal literal Used when encountering the old octal syntax, removed in Python 3. To use the new syntax, prepend 0o on the number. This message can't be emitted when using Python >= 3.0
class MyClass: # Old-style class definition (Python 2)
pass
class MyClass(object): # New-style class definition (Python 3)
pass
Old Ne Operator
Description: Use of the <>
operator Used when the deprecated <>
operator is used instead of "!=". This is removed in Python 3. This message can't be emitted when using Python >= 3.0
if isinstance(my_var, basestring): # basestring is not available in Python 3
print("It's a string")
if isinstance(my_var, str): # Use str instead in Python 3
print("It's a string")
Backtick
Description: Use of the operator Used when the deprecated "
" (backtick) operator is used instead of the str() function
if x <> y: # Python 2 style not-equal operator (invalid in Python 3)
print("x is not equal to y")
if x != y: # Use != operator in Python 3
print("x is not equal to y")
Old Raise Syntax
Description: Use raise ErrorClass(args) instead of raise ErrorClass, args. Used when the alternate raise syntax 'raise foo, bar' is used instead of 'raise foo(bar)'
print "my_var" # Backticks used for repr (invalid in Python 3)
print(repr(my_var)) # Use repr() function instead
Print Statement
Description: print statement used Used when a print statement is used (print is a function in Python 3)
print "Hello, world!" # Python 2 style print statement (invalid in Python 3)
print("Hello, world!") # Python 3 print function