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.