skip to Main Content

VsCode provided venv creation feature. I tried it. Suppose, I have that project structure:

PJFOLDER
├── .venv/*
├── src/
│   └── inner_main.py
├── utils/
│   └── my_utils.py
└── outer_main.py

In both inner_main.py and outer_main.py I have imports of my_utils.py like that:

from utils import my_utils

Python Interpreter selected correctly (even automatically), basic type checker enabled, no errors. When I run outer_main.py via Ctrl+F5 or just Run Python file – everything ok. But when I try to do the exact same thing with inner_main.py it says ModuleNotFoundError: No module named 'my_utils'.

I tried to type python -m src.inner_main, with activated venv ofc, and it worked!

Well, I thought it is because PATH variable, indeed, it has path_to_project/PJFOLDER/.venv/Scripts/ but not my PJFOLDER explicitly.

I tried this code:

import os

path_var = os.environ["PATH"].split(";")
path_var.insert(0, os.getcwd())
os.environ["PATH"] = ";".join(path_var)

But it didn’t help.

Can someone clarify this situation for me, please? How am I supposed to run inner code with inner imports preferably using default VSCode features like debugger and Run Python file? My project in early development and it can have multiple executable .py files and I don’t want to typeselect everything in terminal…

UPD 1:

Based on @Michael Butscher comment. I’ve created file import_fix.py with such code:

import sys
import os

sys.path.insert(0, os.getcwd())

This file lays in .venv folder. Since sys.path contains this folder, I can import it in any file in my project if I need. This file inserts current working directory in sys.path and I can use imports. Though it seems odd. Why doesn’t sys.path contain cwd by default? Maybe there is a better solution? Maybe some setting in VSCode?

2

Answers


  1. Chosen as BEST ANSWER

    Well, there is 2 ways.

    1. Create import_fix.py file as I described above in UPD 1 and place it in .venv folder. You can run your code or debug.
    2. Install Command Variable extenstion. Add new configuration to launch.json.
            {
                "name": "Python Debugger: Module", // you can use whatever name you like
                "type": "debugpy",
                "request": "launch",
                "module": "${command:extension.commandvariable.file.relativeFileDotsNoExtension}",
                "justMyCode": false, // to debug my breakpoints
            }
    

    Select it. Press F5 or Ctrl+F5 to run the debugger. This extension provides correct module name relative to current working directory. If you manage to make it yourselves without third-party extension, please, let me know.

    First way is much simplier to create, but seems odd and you need to import unnecessary file whenever you need to import your code in others directories.

    Second way is about debugging only. Though it's more convenient, strict, you don't need separate file to fix imports, you don't need that little overhead. If you want to run only, then you need to type python -m folders_separated_by_dots.module_name. I belive, there is a way to create custom default command in VSCode to run file as module by default (maybe via tasks.json...), but I'm not smart enough. Still, debugger is enough for me. So, I guess, that's the answer for me. Though you can add useful info.


  2. You either need an __init__.py file in the utils folder or also from ..utils import my_utils should work, since the folder utils is not in the folder where you have inner_main.py, so you need to specify it.

    And that’s why when you run it from the main folder it’s working.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search