Ben Allen
Ben Allen

Reputation: 341

Python Imports in test directory

First off I know this question has been asked 1000 times, but I cant seem to find an answer that works so sorry if this is a repeat, if you know a question that answers this please do share.

I've got the following directory structure:

my_app_dir
    ├── my_app
    │   ├── __init__.py
    │   ├── main.py
    │   ├── services
    │   │   ├── __init__.py
    │   │   └── my_service.py
    │   └── objects
    └── testing
        ├── service_tests
        │   ├── __init__.py
        │   └── test_my_service.py
        └── __init__.py

Im trying to import my_service from ./my_app_dir/my_app/services/my_service.py into my test case class test_my_service.py in ./my_app_dir/testing/service_tests/my_service.py

Im trying to import it in my module like so:

import unittest
from my_app.services.my_service import MyService

class MyTest(unittest.TestCase):
   ...


I get an error: cannot import module my_app...

the twist here is that im trying to run this in VS code with debugging. I have the following launch.json:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "cwd": "${workspaceFolder}"
        }
    ]
}

I did try adding to the PYTHONPATH in the launch.json like this:

"env":{
   "PYTHONPATH":"${PYTHONPATH}C:my_app_dir\\my_app"
} 

This test code needs to be portable to other machines so I would really like to not have to modify the sys path.

Is there an issue with how im importing the module and or the directory structure im using?

Thanks!

Upvotes: 0

Views: 59

Answers (2)

Ben Allen
Ben Allen

Reputation: 341

Simple question gets a simple answer. I was setting the PYTHONPATH incorrectly in the launch.json. I changed it to the following:

"env": {
                "PYTHONPATH": "${workspaceRoot}"
                }

Please correct me if this isn't the best way of doing this.

Upvotes: 0

Tawy
Tawy

Reputation: 629

I am not sure why modifying sys.path would reduce portability:

# my_app_dir/testing/service_tests/my_service.py

import sys, os
initial_sys_path = sys.path.copy()

PATH_TO_MYAPPDIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path.append(PATH_TO_MYAPPDIR)

from my_app.services.my_service import MyService

# If you really want to clean sys.path afterwards
sys.path = initial_sys_path

However, there is also the possibility to use os.chdir as suggested in https://stackoverflow.com/a/61326547/6068769:

PATH_TO_MYAPPDIR = .... # same as above
os.chdir(PATH_TO_MYAPPDIR)
from my_app.services.my_service import MyService

Finally, I am not a VS user, but for the PYTHONPATH solution, I think the variable should point to C:\my_app_dir

"env":{
   "PYTHONPATH":"${PYTHONPATH}C:my_app_dir"
} 

Upvotes: 1

Related Questions