21

I am trying to build a new package, however, when I try to run any of the files from inside VSCode or from terminal, I am coming across this error:

ModuleNotFoundError: No module name 'x'

My current folder structure is as follows:

package
|---module
|------__init__.py
|------calculations.py
|------miscfuncs.py
|---tests
|------__init__.py
|------test_calcs.py
|---setup.py
|---requirements.txt

However, when I run my tests (PyTest) through VSCode and using import module.calculations as calc or from module.calculations import Class in test_calcs.py, the tests work as expected - which is confusing me.

I know this is a commonly asked question, but I cannot fathom out a solution that will work here.

I have tried checking the working directory is in system path using the code below. The first item on the returned list of directories is the one I am working in.

import sys
print(sys.path)

I have also used the following in the files to no avail:

import module.calculations 
import .module.calculations
from . import miscfuncs

When trying import .module.calculations, I get the following:

ModuleNotFoundError: No module named '__main__.module'; '__main__' is not a package

When trying from . import miscfuncs in calculations.py, I get the following error:

ImportError: cannot import name 'miscfuncs'

When working on a file within the module folder, I can use a relative import: import calculations and it works fine. This is fine for files within module, but not when I am working in test_calcs.py.

In my setup.py, I have a line for:

packages=['module']

Happy to post more info if required or a link to my repo for the full code.

EDIT

Following remram's solution:

I have updated launch.json to include the CWD and PYTHONPATH variables.

The module name is still not recognised, however, IntelliSense within VSCode is picking up the functions within the imported file just fine.

"version": "0.2.0",
"configurations": [
    {
        "name": "Python: Current File",
        "type": "python",
        "request": "launch",
        "program": "${file}",
        "console": "integratedTerminal",
        "cwd": "${workspaceFolder}",
        "env": {"PYTHONPATH": "${cwd}"
        }
    }
    ]
scrpy
  • 985
  • 6
  • 23
rockdoctor
  • 385
  • 1
  • 3
  • 11
  • 7
    I was stuck on this for a long time. The key to me figuring this out was studying the difference between VSCode and PyCharm in their treatment of the concept of a source, or root, directory. In PyCharm things are made very easy for you, but in VSCode you have to go through a bit more trouble. I changed both the launch.json and settings.json file to define the PYTHONPATH as "terminal.integrated.env.linux": {"PYTHONPATH": "${workspaceFolder}/src",}, – Lepidopterist Jul 21 '21 at 01:36
  • 3
    @Lepidopterist Thank you so much!! I was on it for 2 hours, until I was your comment. My colleague is working on PyCharm and it worked great for him, by when I tried to run it, I got this "Module Not Found" Error. I realized the only difference is the IDE, but couldn't find what to do so it works. All I needed to do is, as you wrote, add this line: "terminal.integrated.env.windows": { "PYTHONPATH": "${workspaceFolder}/.", }, to my settings JSON file in VSCode. – AlonBA Jun 22 '22 at 11:32

6 Answers6

14

@lepidopterist comment proved to be the game-changer of hours of struggling...

Solution:

  1. Press Ctrl + Shift + P to open Command Palette
  2. Go to Users.setting.json
  3. Add the following line

"terminal.integrated.env.windows": { "PYTHONPATH": "${workspaceFolder}" }

For Reference: Settings.json

Explanation:

This was my project structure... Project

I had three modules/packages inside my project!

  • module_a + module_b : performing standalone tasks
  • convenience: provides utility functions to all other modules

What I wanted to do!

  • keep all utility functions inside the convenience module and import them to whichever module that requires them

What did-not work!

  • Relative imports failed

from ..convenience.utilities import add

gave...

beyond top level package error
  • Absolute imports also failed

from convenience.utilities import add

gave...

ModuleNotFoundError: No module named 'convenience'
  • Adding Workspace directory to PYTHONPATH also failed

"env": {"PYTHONPATH": "${workspaceFolder}"}

gave...

ModuleNotFoundError: No module named 'convenience'

Why the Solution (I mentioned at Start!) worked?

  • Because, I was running the module_a/task.py using the integrated terminal. It makes sense that, Pythonpath needs to be appended for the terminal where we add the path of our workspace directory.

(One thing to note): My OS was windows so it was...

"terminal.integrated.env.windows"

For Linux it would be...

"terminal.integrated.env.linux"

Result after Modifying Users.Setting.json:

Output

haider abbasi
  • 163
  • 2
  • 7
7

Make sure you are running from the package folder (not from package/module) if you want import module.calculations to work. You can also set the PYTHONPATH environment variable to the path to the package folder.

remram
  • 4,805
  • 1
  • 29
  • 42
  • 1
    How can I run from the package folder in VSCode? I guess the green run button is executing the file in its current location? Also, if I set PYTHONPATH, how will that impact other users using the library when they pip install? – rockdoctor Jun 14 '20 at 06:54
  • Check out this question: https://stackoverflow.com/questions/38623138/vscode-how-to-set-working-directory-for-debug. Setting `PYTHONPATH` would not impact other users, so long as you set it to what is standard (e.g. the top-level directory, where your `setup.py` is) – remram Jun 14 '20 at 15:24
  • 1
    I have followed the reply by CermakM for setting the CWD and `PYTHONPATH` by adding `"cwd": "${workspaceFolder}"` and `"env": {"PYTHONPATH": "${cwd}"` to launch.json. The error is still occurring when using absolute imports in files contained within tests and in module directories. I'm probably missing something simple. – rockdoctor Jun 16 '20 at 08:01
  • 1
    I found that in some cases, I can still run within a subfolder. But in a different project, this error occurs. – Chang Mar 04 '22 at 01:20
  • @remram What was the solution here? I'm having trouble following how this solved the problem especially reading through these comments it seems like it is unresolved. – SPYBUG96 Dec 28 '22 at 17:47
  • I'm sorry you are having trouble, I don't know what to say but repeat the information above. What have you tried and what happened? Consider opening another question, this is not a great place to troubleshoot. – remram Dec 29 '22 at 18:54
4

In order to debug main.py VSCode needs to know explicit library paths. This can be done by setting the environment ('env') variable in launch.json. First step is create a 'launch.json' inside the .vscode folder.

/
├── .vscode/
│   └── launch.json
├── mySubdir/
│   └── myLib.py
└── main.py

If main.py wants to import myLib.py as module, VSCode can only do this if mySubDir is part of the Python path.

Example launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "cwd": "${fileDirname}",
            "env": {"PYTHONPATH": "${workspaceFolder}/mySubdir:${env:PYTHONPATH}"},
        }
    ]
}

{workspaceFolder} is a predefined variable which will be substituted by VSCode. I also used {pathSeparator} but found it doesn't work in Linux, so now I use ':' instead.

This thread gives a more extensive explanation: How to correctly set PYTHONPATH for Visual Studio Code

FrankyHollywood
  • 1,497
  • 19
  • 18
1

According to your description, I don't have gotten enough information, but I think I can speculate there are two key points you haven't been aware of.

  • The relative import be used only inside package (or module).

    Referring to python official documentation Modules

    Note that relative imports are based on the name of the current module. Since the name of the main module is always __main__, modules intended for use as the main module of a Python application must always use absolute imports.

    Even if calculations.py is inside package, but you run it as 'main module', it does also not work.

  • The absolute import's module (your own) should be located under the your current work directory (under the path which is in either sys.path or env PYTHONPATH)

    For the issue that it works fine in test, I think it depends on the directory where your 'main module' working, you should check it carefully.

You just need to address this two points, you will work out your problem.

yixuan
  • 375
  • 2
  • 17
0

What worked for me was using the pyproject.toml file:

[tool.pytest.ini_options]
pythonpath = [
  "."
]
adam13
  • 91
  • 4
0

Instead of

"program": "${file}"

try

"module": "folder.pythonfilename"

without the ".py" at the end.

Ate Somebits
  • 287
  • 1
  • 18