0

Edit: Slightly cleaner solution:

Don't make a separate workspace for your code (unless you want it, in which case mostly follow the guide below), and instead of putting a .vscode folder in the parent root folder, open up the workspace launch config from the Run and Debug menu on the left. Make it look something like this:

{
    "folders": [
        {
            "path": "%path to parent%/parent"
        }
    ],
    "settings": {},
    "launch": {
    "version": "0.2.0",
        "configurations": [
            {
                "name": "Launch Python parent",
                "type": "python",
                "request": "launch",
                "program": "${file}",
                "console": "integratedTerminal",
                "cwd": "${workspaceFolder}\\extensions\\mycode", // <-- Important
                "env": {"PYTHONPATH": "${workspaceFolder}; ${workspaceFolder}\\extensions\\mycode; ${env:PYTHONPATH}"} // <-- Important
            }
        ]
    }
}

Not much cleaner, but you don't have to modify the parent project or set up multiple workspaces.


Not so much a question, but a solution to the very specific problem I had. Might be a duplicate of vscode import error for python module or ModuleNotFoundError - Python VSCode I can´t import modules:

I am working on an extension for an extension for a parent project. The folder structure looks something like:

parent/
  extensions/
    mycode/
      myutils/
        IMyModule.py
        MyModule.py
      myscripts/
        myscript.py
  utils/
    __init__.py
    modules.py
  scripts/
    script.py

where myscript.py wants to

# myscript.py
 
from utils.modules import Module
from myutils.mymodule import MyModule

and MyModule.py wants to

# MyModule.py

from IMyModule import IMyModule

(I'm trying out OOP for the first time)

This lead to the dreaded ModuleNotFoundError: No module named 'myutils'

tl;dr Put __init__.py in the proper places and add a .vscode/launch.json to the parent directory.

Several things had to happen to fix this problem (for my method, anyway), and I have confirmed that (most) every step was necessary.

First, I didn't know about __init__.py (I'm new to Python, so I had to google this). I'm leaving this part in in case some other newbie doesn't know about that and is having this same problem.

So I added __init__.py to the myutils folder with contents that look like this:

# myutils/__init__.py

from .IMyModule import *
from .MyModule import *

I also had multiple nested folders in there, so an __init__.py went in every subfolder.

This alone still gave me the ModuleNotFoundError.

After that didn't work, (and after much trial and error), I imported the parent folder as a second workplace in VSCode by going into File->Add Folder to Workspace... (This may not be necessary. See below).

In addition, I added a .vscode folder with a launch.json file into mycode/. The launch.json looks like this:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "cwd": "${fileWorkspaceFolder}",
            "env": {"PYTHONPATH": "${workspaceFolder:parent}; ${workspaceFolder:mycode}; ${env:PYTHONPATH}"}
        }
    ]
}

Unpacking this,

"cwd": "${fileWorkspaceFolder}" 

makes the working directory for parent files remain in parent/, but the working directory for mycode files becomes mycode/. This makes sure I can still run parent's code while also being able to run my code separately.

"env": {"PYTHONPATH": "${workspaceFolder:parent}; ${workspaceFolder:mycode}; ${env:PYTHONPATH}"} 

says to Python, "look in parent/ for parent's packages, mycode/ for mycode's packages, and keep the current PYTHONPATH in case there's something in there." This is why I added mycode as a separate workspace (now that I think about it, that may have not been necessary if you change

${workspaceFolder:parent}; ${workspaceFolder:mycode} 

to

${workspaceFolder}; ${workspaceFolder}/extensions/mycode

but I'm too lazy to test that now).

All of this together, and tada! Working myscript.py that can import code from myutils/, call parent code, and also parent code still works on its own.

The final directory structure looks like:

parent/
  .vscode/
    launch.json
  extensions/
    mycode/
      myutils/
        __init__.py
        IMyModule.py
        MyModule.py
      myscripts/
        myscript.py
  utils/
    modules.py
  scripts/
    script.py

Any comments and suggestions are welcome, especially if there's a simpler method to solve this particular problem.

2 Answers2

0
# MyModule.py
from extensions.mycode import myutils
from myutils import MyModule`

This code should work well because when you see the PATH tree, you can observe that extensions and utils are on the same level.

Alexander L. Hayes
  • 3,892
  • 4
  • 13
  • 34
  • Ah, I see! I had to start from extensions to import that properly. I was always trying to start from myutils, and of course, that didn't work. Thanks! – DrifterOfTime Dec 23 '22 at 03:22
  • I actually still have the same problem with this code in VSCode. PyCharm also has the same problem with `from myutils import MyModule`, but `from extensions.mycode import myutils` works. – DrifterOfTime Dec 23 '22 at 04:22
  • If I put "cwd": "${workspaceFolder}\\extensions\\mycode", "env": {"PYTHONPATH": "${workspaceFolder}; ${workspaceFolder}\\extensions\\mycode; ${env:PYTHONPATH}"} in the launch config, though, it works. Dunno why. – DrifterOfTime Dec 23 '22 at 04:36
0

Usually, vscode takes the workspace you open as the root directory.

For your first file, you can use the following codes to import your module:

# myscript.py
 
from utils.modules import Module
from extensions.mycode.myutils.mymodule import MyModule

And if you used pycharm once, pycharm compiles files in the directory where the current running files are located. You can search "Terminal: Execute In File Dir" in the settings and check it:

enter image description here

MingJie-MSFT
  • 5,569
  • 1
  • 2
  • 13
  • Thank you for that solution! I would rather not have to run PyCharm. Maybe I should switch to PyCharm, though. I've heard good things. I've only tried the community edition, and it works just fine for Python, at least. I do like VSCode better than the CE for it's versatility, though. – DrifterOfTime Dec 23 '22 at 03:26
  • No, no, I mean, if you are familiar with pycharm and want the module import structure to be the same as pycharm, you can make supplementary settings for vscode :) – MingJie-MSFT Dec 23 '22 at 04:00
  • Actually with that setup, I still have the same problem, even with this code (I followed my own guide exactly instead of using the extension I'm actually working on). Still get `ModuleNotFoundError`. For clarification, `print(os.getenv("PYTHONPATH"))` returns None unless I add a launch.json or add a launch profile in the workspace. If I add `${workspaceFolder}` to `PYTHONPATH`, then `from utils.modules import Module` works but `from extensions.mycode.myutils.mymodule import MyModule` doesn't. It might have something to do with the Python path/version I'm using. – DrifterOfTime Dec 23 '22 at 04:18
  • It doesn't really work in PyCharm, either. `from utils.modules import Module` works, but `from extensions.mycode.myutils.mymodule import MyModule` doesn't. No idea what I'm doing wrong. I assume it's something I'm doing if you guys can get it to work without a launch.json. – DrifterOfTime Dec 23 '22 at 04:28
  • yep, as long as I can figure out how! @MingJie-MSFT – DrifterOfTime Dec 23 '22 at 04:31
  • As for your problem, I think the import method I have given has solved this problem. The supplementary content is not a solution, but a supplement to the unaccustomed default running path for pycharm user. – MingJie-MSFT Dec 23 '22 at 05:26
  • If you do not check this option, the workspace is the directory where files are run in vscode. It can find files. If you check this option, it is the directory where files are run. Pycharm defaults to the latter – MingJie-MSFT Dec 23 '22 at 05:27