import python class into another folder in a package - python

I'm trying to import a python class from another folder of my python package but I this error "No module named models".
It's a Flask project.
-app
|-run.py
|-myapp
|- libs
|- updateto
|- __init__.py (empty)
|- connection.py
|- removeto
|- __init__.py (empty)
|- static
|- templates
|- __init__.py (NOT empty)
|- routes.py
|- models.py
My init.py:
from flask import Flask
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///maindb.db'
from models import db
db.init_app(app)
import myapp.routes
In my models.py I've a class named: application
And in connection.py I want import my class "application".
I've try with "from models import application" but I've this error "no modules named models".
I think it's possible to reach this goal with the modification of the init.py in the "updateto" folder but I'm no sure because I don't clearly understand the functioning of the init.py file...
Thanks
EDIT:
Which is weird, it's if under connection.py I add "import myapp" and "print(help(myapp))", I've this output:
Help on package myapp:
NAME
myapp
FILE
c:\app\myapp\__init__.py
PACKAGE CONTENTS
libs (package)
models
routes
DATA
app = <Flask 'myapp'>
But if I try "from myapp import models" I've this error "ImportError: cannot import name models"
EDIT2:
If I try to add in connection.py "from myapp import app", it works but not if I try to import models... I'm very surprised. I've try to add in myapp/init.py:
__all__ = ["models", "routes]
But same error...
EDIT3:
hummmm I've move all my modules under the libs folder into myapp and when I try to put in connection.py "from model import application" I've always the same error "ImportError: cannot import name application"
Other test in connection.py:
import models
print(models)
Output:
<module 'myapp.models' from 'C:\app\myapp\models.pyc'>
I can import my module named models but I can't import the class under models.py
EDIT4:
Ok, I think I found the problem. It's my ini.py in myapp, because if I comment this file content, the connection.py can now import my class application in models. I run the file run.py which uses routes.py and it's him that calls operation.py
With some tests, I've find the lines who create my error:
from models import db
db.init_app(app)
import myapp.routes
But why????

I don't know about Flask specifically, but in Python you should generally include a __init__.py in every folder and subfolder for them to be recognised as modules and/or packages.
In the diagram you provide, there is no __init__.py in the app folder. Try putting one and re-post if that resolves your problem.
If it doesn't work, try:
import os
print(os.getcwd())
If the current working directory isn't the app directory, you'll have to work around this. One way would be:
import sys
sys.path.append('/path/to/app')
import myapp.models
You can always see what directories are in your search path for modules by checking sys.path.
Update: Sorry I just realized that maybe you' re trying to run connections.py as a script. That would change you working directory to that of connections.py. Try importing connections.py from your main script with import models inside connections.py and see if you get an error.
Update (in reply to Edit 4): (I don't have enough reputation points to comment yet, so I reply here)
from models import db
db.init_app(app)
import myapp.routes
The problem in this piece of code is the import myapp.routes. Change that to import routes and it should work. As a rule of thumb, your main script's directory is your root directory. You can import any module located in your root directory from inside any other module (even modules inside a sub-folder!) with a simple import module.

Related

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
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

How to import models from outside Django BASE_DIR

I am working on a Django app in which I want to import some class/function from generator.py into my views.py to process an user-submitted input. My folder structure looks like this:
project/
models/
__init__.py
generator.py
web/
django/
__init__.py
settings.py
urls.py
wsgi.py
django_app
__init__.py
views.py
etc.
Inside views.py, I have
from ...models.generator import Generator
When I try to run server, what I get is:
ValueError: attempted relative import beyond top-level package
I've seen many answers, but most are about manipulating sys.path or changing PYTHONPATH. I'm not sure how and where to do either cause I'm rather new to Django.
Can someone tell me exactly which commands to run to allow the import to be done?
Import of python is based on sys.path and cannot be outside the top-level dir. More information.
That's mean, if you append top of BASE_DIR path in sys.path you can import. But it's a tricky way.
def import_function():
import sys
sys.path.append(os.path.dirname(BASE_DIR))
module = __import__('models.generator') # import code
sys.path.pop()
return module
g_module = import_function()
g_module.Generator

Cannot import app modules implementing Flask CLI

For some reason when I try to execute my custom command:
flask create_user
I get an error whenever I try import anything from my src folder:
File "/app/backend/flask_app/command.py", line 17, in seed_db
import src.models
ModuleNotFoundError: No module named 'src'
/
__init__.py
command.py
run.py
src/
__init__.py
models/
__init__.py
user_model.py
command.py
import click
from flask import Flask
from flask.cli import with_appcontext
app = Flask(__name__)
#app.cli.command()
#with_appcontext
def create_user():
import src.models as models
print("hello")
app.cli.add_command(seed_db)
I found the solution.
I had to delete the root dir __init__.py file.
I found this answer from the famous Miguel Grinberg:
https://github.com/miguelgrinberg/flasky/issues/310#issuecomment-340641813
These files (__init__.py) make python believe the main directory of the package is one directory above, so that is the directory that is added to the Python path. Usually you want your top-level directory to not be a Python package, so that the current directory goes to the path.
__
It is a matter of python way of import modules, not about Flask command.
Since command.py file is at the same level of the models folder you can just write:
import models.user_models as users
After that you can acces the user_models module from users reference:
import models.user_models as users
users.some_function_name()

relative import does not work in Python

I have a project structure like this...
app/
main.py
app/
__init__.py
boot.py
server.py
controllers/
__init__.py
home.py
The imports are...
# main.py
from app import server
# server.py
from . import boot
# boot.py
from . import controllers
# controllers/__init__.py
from . import home
# controllers/home.py
from .. import boot
Now all the imports are working except the last one. The error thrown is...
ImportError: cannot import name boot
What's the problem? (I am using Python 3.2)
You are importing boot which is importing controllers, which is then asked to import home, and home then tries to import boot, but it wasn't done importing yet. Don't do this, you are creating a circular dependency here.
Also see Circular import dependency in Python

Django ImportError

I created my own Django application with directory structure
/appname
__init__.py
models.py
/submodule1
__init__.py
a.py
Inside a.py I have the following import
from ..models import Something
This works okay if I have /appname inside my /djangoproject folder, but when I install the app to Python's site-packages (via setup.py which I created), all hell breaks loose and a.py can no longer import Something, with the following error:
ImportError: cannot import name Something
Here is the setup.py:
from distutils.core import setup
setup(name='appname',
version='0.1',
packages=['appname', 'appname.contrib'],
)
It turns out that it was a circular import error. models.py was importing a.py and a.py was importing models.py.
Breaking this circle solved the import issues, but now it is time to figure out how to do lazy evaluation in Python :-)
Put empty file named: __init__.py inside /submodule1 so Python can parse it as module. It should help. The same in /appname - there should be also __init__.py file

Categories