user10317280
user10317280

Reputation:

Python can't import module from package

I have a flask restful project with the following layout (file names changed for convenience)

myproject/
    __init__.py
    app.py
    common/
        __init__.py
        util.py
    foo/
        __init__.py
        main.py
        utilities.py

foo/ is just a folder containing code for one of the API endpoints, I'm planning to add others in the future, for this reason I have common/util.py file which contains reusable functions that I will use with other API endpoints.

foo/main.py

from flask_restful import Resource, request

from utilities import Analysis

class Foo(Resource):
    def get(self):      
        pass

in foo/utilities.py I have classes with methods that get some data, I import those classes to foo/main.py to return JSON response

classes in foo/utilities.py also uses some functions from common/util.py but when I try to import something from common/util.py to foo/utilities.py I get import common.util ModuleNotFoundError: No module named 'common'

What could be causing this? I tried importing various ways: from common.util import my_func from .common.util import my_func from myproject.common.util import my_func

but none worked.

This is myproject/app.py in case it matters:

from flask import Flask
from flask_restful import Api

from foo.main import Foo

app = Flask(__name__)
api = Api(app)

api.add_resource(Foo, '/Foo')

if __name__ == "__main__":
    app.run()

I'm doing all of this in activated virtualenv if it matters

Upvotes: 3

Views: 8291

Answers (1)

phd
phd

Reputation: 94755

from common.util import my_func

In Python 3 this is an absolute import, that is, the directory with common/ subdirectory must be in sys.path. In your situation it's certainly a wrong approach.

from .common.util import my_func

This import expects common to be a subdirectory of foo which is also not the case.

from myproject.common.util import my_func

This is finally the best approach but for it to work the parent directory of myproject/ subdirectory must be in sys.path. Either you install the entire myproject or add the parent directory to $PYTHONPATH environment variable or add the directory to sys.path in foo/main.py. Something like:

PYTHONPATH=/home/to/parentdir /home/to/parentdir/myproject/foo/main.py

or

import sys
sys.path.insert(0, '/home/to/parentdir')

/home/to/parentdir is the directory where myproject/ is.

After installing myproject or adding its parent directory to sys.path you can also use relative import. You need to remember that common is a sibling package comparing to foo so the import must be not from .common but from ..common:

from ..common.util import my_func

Upvotes: 2

Related Questions