16

I just put together the following "minimum" repro case (minimum in quotes because I wanted to ensure pylint threw no other errors, warnings, hints, or suggestions - meaning there's a bit of boilerplate):

pylint_error.py:

"""
Docstring
"""

import numpy as np


def main():
    """
    Main entrypoint
    """
    test = np.array([1])
    print(test.shape[0])


if __name__ == "__main__":
    main()

When I run pylint on this code (pylint pylint_error.py) I get the following output:

$> pylint pylint_error.py
************* Module pylint_error
pylint_error.py:13:10: E1136: Value 'test.shape' is unsubscriptable (unsubscriptable-object)

------------------------------------------------------------------
Your code has been rated at 1.67/10 (previous run: 1.67/10, +0.00)

It claims that test.shape is not subscriptable, even though it quite clearly is. When I run the code it works just fine:

$> python pylint_error.py
1

So what's causing pylint to become confused, and how can I fix it?

Some additional notes:

  • If I declare test as np.arange(1) the error goes away
  • If I declare test as np.zeros(1), np.zeros((1)), np.ones(1), or np.ones((1)) the error does not go away
  • If I declare test as np.full((1), 1) the error goes away
  • Specifying the type (test: np.ndarray = np.array([1])) does not fix the error
  • Specifying a dtype (np.array([1], dtype=np.uint8)) does not fix the error
  • Taking a slice of test (test[:].shape) makes the error go away

My first instinct says that the inconsistent behavior with various NumPY methods (arange vs zeros vs full, etc) suggests it's just a bug in NumPY. However it's possible there's some underlying concept to NumPY that I'm misunderstanding. I'd like to be sure I'm not writing code with undefined behavior that's only working on accident.

stevendesu
  • 15,753
  • 22
  • 105
  • 182

3 Answers3

10

I don't have enough reputation to comment, but it looks like this is an open issue: https://github.com/PyCQA/pylint/issues/3139

Until the issue is resolved on their end, I would just change the line to

    print(test.shape[0])  # pylint: disable=E1136  # pylint/issues/3139

to my pylintrc file.

ignoring_gravity
  • 6,677
  • 4
  • 32
  • 65
  • 1
    Thanks for linking the issue. Unfortunately `pylint` ***also*** complains about lines being too long, so I think I may stick with `print(test[:].shape[0])` over your solution since it makes my lines shorter and saves me from `pylint`s incessant nagging – stevendesu Oct 31 '19 at 17:04
  • 2
    NOTE: Recent versions of pylint warn about disabling by ID, so I recommend something more like this on the preceding line: `# pylint: disable=unsubscriptable-object # pylint/issues/3139` – Bryce Schober Mar 30 '20 at 21:56
3

As of November 2019:

As mentioned by one of the users in the discussion on GitHub you could resolve the problem by downgrading both pylint and astroid, e.g. in requirements.txt

astroid>=2.0, <2.3
pylint>=2.3, <2.4

or

pip install astroid==2.2.5 & pip install pylint==2.3.1
Tomasz Bartkowiak
  • 12,154
  • 4
  • 57
  • 62
1

This was finally fixed with the release of astroid 2.4.0 in May 2020.

https://github.com/PyCQA/pylint/issues/3139

Tomi Aarnio
  • 2,446
  • 1
  • 19
  • 14