Importing a module into a custom command - python

Suppose I have the following Django project:
/ # Project dir
/myapp # App dir
/myapp/views.py # views file
/myapp/mymodule.py # a Python module
/myapp/management/commands/mycommand.py # command file
In the views file, I can import mymodule.py by simply writing import mymodule in views.py. However, if I do the same in mycommand.py, I get the error: ImportError: no module named mymodule. I know that to import a model, I can write from myapp.models import mymodel, but mymodule is not a model, it is a separate Python module. So, how do I import this moduel into my command file?

Thats because of where mymodule is in relation to all of your other files.
If you type
from myapp import mymodule
In mycommand.py as long as you have set up your __init__.py files correctly in myapp and are using a setup.py file you should be fine. The modules documentation has more information on this

The fact that you are unable to do this means your myapp folder is not in the python's sys.path. The reason it worked in views.py is because mymodule.py is in the current directory of views.py
Assuming your Project dir (/) is in the python's sys.path:
Add a file __init__.py in myapp directory. This file can be blank.
Then you can do import myapp.mymodule or from myapp import mymodule
The same logic applies for n levels deep. If you have myapp/myappdir1/myappdir2/myfile.py you can do import myapp.myappdir1.myappdir2.myfile assuming each of these have __init__.py file in them.
Check https://docs.python.org/2/tutorial/modules.html#the-module-search-path for python's module search path

Related

ImportError with absolute and relative imports

Having trouble importing with a very simple file structure.
My file structure looks like this:
project/
...
project.py
helper.py
__init__.py
...
Within project.py is the class I am trying to import in helper
#project.py
class MyAPIOne():
...
class MyAPITwo():
...
#helper.py
import MyAPIOne
if __name__ == "__main__":
api = MyApiOne()
...
When running with python3 helper.py:
If I keep the absolute import import MyAPIOne I recieve ModuleNotFoundError: No module named 'MyAPIOne'
If I change it to a relative import from . import MyAPIOne I receive ImportError: cannot import name 'MyAPIOne'
I have also experimented with appended to sys.path various directories, with no luck.
If you are running this script from the project folder, you can alter your import the following way: from project import MyAPIOne.
Also, you can add this folder to your PYTHONPATH env variable.
Upd: to add some folder to PYTHONPATH you can ran
export PYTHONPATH="${PYTHONPATH}:/my/other/path"
main file can import all the files, but main file can't be imported by other files.
once file mentioned with __name__ = "__main__", then it becomes main file. so helper.py is acts as main file. it can't be imported.

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 in Python 3.6

I want to use relative import in Python 3.
My project:
main_folder
- __init__.py
- run.py
- tools.py
I want to have in run.py (MyClass declared in __init__.py):
from . import MyClass
And in run.py:
from .tools import my_func
An ImportError is raise.
Alternatively, with absolute import, debugging in PyCharm does not work and the library takes from installed packages, not my directory.
I know one way, but it is terrible:
sys.path.append(os.path.dirname(os.path.realpath(__file__)))
How to use this import in my project?
When you use PyCharm, it automatically makes the current module main, so relative statements like from . import <module> will not work. read more here.
to fix your problem, put the __init__.py and tools.py files in a sub-directory
main_directory/
run.py
sub_directory/
__init__.py
tools.py
in your run.py file, write the following as your import statements
from sub_directory import tools
from sub_directory.__init__ import MyClass
Edit: as #9000 mentioned, you can write from sub_directory import MyClass and achieve the same thing.

Django importing another file from another package

I have the following folder structure
app/
app/helpers/
app/helpers/methodhelper.py
app/methods/
app/methods/method.py
and I'm trying to import a function from methodhelper.py inside method.py
so I tried the following:
import app.helpers.methodhelper
OR
from app.helpers.methodhelper import function1
OR
import helpers.methodhelper
and I get:
"No module named app.helpers.methodhelper"
Important to note: helpers/__init__.py already exists
How should this be done ?
Your Django project's default path is in the root directory of the project (where the manage.py file is). You can either add the sub directories below that to your PYTHONPATH (easily done by appending to sys.path) or you can import that function using the full module path:
from projectname.app.helpers.methodhelper import function1
When I start a Django project, I always add
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
to my settings.py. This path looks similar to /home/kyle/django_project_name/. Inside that directly is manage.py.
From there, also in my settings.py, I include:
sys.path.append(os.path.join(PROJECT_ROOT, 'django_project_name'))
This makes my apps importable without the need to include my project name in the module path.
you need to add the module in settings.py file

Cannot import modules of parent packages inside child packages

I have a parent package that has 2 child packages. It looks like this
backend
__init__.py
conf.py
db.py
connections.py
/api
__init__.py
register.py
api.py
/scheduled
__init__.py
helpers.py
All the __init__.py files are empty.
The code in backend/connections.py and backend/conf.py is being used by modules in both packages api and scheduled.
in register.py i have code like
from backend.conf import *
from backend.connections import *
Now when i do python register.py
i get this error
ImportError: No module named backend.conf
Also when i changed from backend.conf import * to from ..conf import * or from .. import conf i get this error
ValueError: Attempted relative import in non-package
What i understand by the above error is that python is not treating the above folders as packages. But i have __init__.py in all the folders. What is wrong?
When you run python register.py, your backend/register.py file is used as the __main__ module of the program, rather than as a module within the backend package. Further more, the Python import path will not automatically include the directory containing the backend directory, which is probably the cause of your problems.
One option that might work is to run your program as python -m backend.register from the top level directory of your project (or set PYTHONPATH so this module can be found). This will search for the script on the normal import path, and then run it as the main program.

Categories