30

I have a project structured like this:

.
└── myapp
    ├── app.py
    ├── models
    │   ├── hello.py
    │   └── world.py
    └── requirements.txt

I have two models, hello and world. Both models are used from app.py where I import them like this:

from models.hello import Hello
from models.world import World

But world also needs to use hello. I tried this in world.py:

from models.hello import Hello

The above technically works when I run the app, but VSCode's Python extension gives me the following error:

E0401:Unable to import 'models.hello'.

What is the proper way of importing a submodule from the same directory? How do I avoid this error in VSCode?

Jimmy Sanchez
  • 721
  • 2
  • 7
  • 17

5 Answers5

34

The error you are receiving is one that's reported by a python linter named pylint. So the problem isn't really specific to the vscode extension.

There are two solutions:

  1. Please try adding an .env file in your project directory with the vape PYTHONPATH=./myapp, this will tell pylint where to find your modules

  2. Or just open the folder myapp in vscode directly instead of opening the parent directory in vscode.

siyb
  • 2,837
  • 2
  • 21
  • 18
Don
  • 6,632
  • 3
  • 26
  • 34
  • 5
    Using the `.env` file solves the problem I had with VS Code being unable to ctrl+click navigate to imported local classes. Thanks! – cb2 Jul 18 '19 at 06:57
  • 2
    I seem to be too stupid for this. Could you please more specific and give an example with a reference to a venv? I don't get the myapp definition as well. Thanks – Christian Jul 31 '19 at 13:17
  • 4
    @Christian you create a `.env` file at the root of your project and inside of it put the variable `PYTHONPATH=path_to_your_package`. In the author example the path to is package from the root is `./myapp` so he needed to put in the env file the variable `PYTHONPATH=./myapp` – SmileyProd Aug 10 '19 at 12:02
8

The error is coming from pylint. You need to add this line into settings.json file (VS Code):

"python.linting.pylintArgs": ["--init-hook",
        "import sys; sys.path.append('<absolute path to myapp directory>')"],
Shtefan
  • 742
  • 12
  • 14
  • 1
    I have a venv for every project. Which abolute path is ment? – Christian Jul 31 '19 at 13:13
  • I do not use venv. But as per the doco, you can try to play with these parameters: sys.prefix and sys.exec_prefix. https://docs.python.org/3/library/venv.html – Shtefan Aug 02 '19 at 12:54
  • Another option just to switch to a different linter. Recently I started to use flake8 and so far no trouble at all. – Shtefan Aug 02 '19 at 13:00
  • I've been searching for hours and this fixed it! Thanks! – oriont Jul 08 '20 at 00:12
  • What is wrong with using from models.hello import Hello? Is there any explanation of the error or is it that the vs extension is not able to understand imports correctly? – variable Aug 11 '20 at 09:01
  • It is an extension issue. Try to use any other linter for the same code. A real issue has to be highlighted by any linter. – Shtefan Aug 12 '20 at 03:48
4

Since hello.py and world.py are in the same folder (aka package), you should import the Hello class in world.py as follow:

from .hello import Hello

As described in this thread: What does a . in an import statement in Python mean?

The . is here to indicate the import from the current package.

Alexis.Rolland
  • 5,724
  • 6
  • 50
  • 77
  • 7
    This solves the vscode error buy breaks the application. `app.py` is the entry point for the application, so even in **world.py** I can't import from **hello** because **hello** is in **models** and not the project root directory. I get `no module named 'hello'` – Jimmy Sanchez Feb 25 '18 at 13:45
  • @JimmySanchez you're correct, I have updated my answer. It should be `from .hello import Hello` – Alexis.Rolland Feb 26 '18 at 02:53
  • What is wrong with using `from models.hello import Hello`? Is there any explanation of the error or is it that the vs extension is not able to understand imports correctly? – variable Aug 11 '20 at 09:01
4

In your your .vscode/settings.json (in the root directory of your workspace) you need these two lines:

one to use the pylint in your virtual environment (if you have one) so that pylint is aware of it. You'll want to adjust the below if your pylint or virtual environment is located in a different place.

  "python.linting.pylintPath": "${workspaceFolder}/api/venv/bin/pylint"

and one, as Shtefan mentions above, to let pylint know where the python part of your project is:

  "python.linting.pylintArgs": [
    "--init-hook",
    "import sys; sys.path.append('${workspaceFolder}/api')"
  ]

This additional line may be helpful if you don't already have vscode setup with your virtual environment, once again you may have to modify if your virtual environment path does not match the below.

  "python.pythonPath": "${workspaceFolder}/api/venv/bin/python",
Scott Guthart
  • 407
  • 5
  • 8
0

You're missing an __init__.py file in the directory models/. At the very least, you need an empty file called models/__init__.py. With this, so long as you run python from the myapp/ directory, you will be able to do from models.hello import Hello.

Malcolm
  • 2,394
  • 1
  • 23
  • 26