Can't import module from sibling directory - python

I have a Python 3 project that's structured like this:
/project
__init__.py
/models
__init__.py
my_model.py
base_model.py
/tests
__init__.py
test.py
In test.py I want to import my_model. My first attempt was from models import my_model, which threw an ImportError: No module named 'models'. This question recommended adding an __init__.py file to each directory, which didn't help. Another post said to modify the path with:
import sys; import os
sys.path.insert(0, os.path.abspath('..'))
but this throws an error when my_model tries to import from base_model.
This seems really straightforward but I'm stumped. Does anyone have any ideas?

Adding the sibling directory to sys.path should work:
import sys, os
sys.path.insert(0, os.path.abspath('../models'))
import my_model

Use absolute imports everywhere: from project.models import my_model, should work fine from wherever in your project, no need to mess with paths either.

The answer depends on how you launch test.py.
The only way I know to do relative imports is to have the file in a package. For the Python interpreter to know you're in a package is to import it in some way.
Use:
from ..models import my_model
in test.py
And launch the Python Interpreter below the project folder.
You will then be able to import project.tests.test without error.

Related

Import file from subdirectory into file in another subdirectory

I have a python project a folder structure like this:
main_directory
main.py
drivers
__init__.py
xyz.py
utils
__init__.py
connect.py
I want to import connect.py into xyz.py and here's my code:
from utils import connect as dc
But I keep getting this error no matter what I do, please help:
ModuleNotFoundError: No module named 'utils'
Update: People are telling me to set the path or directory, I don't understand why I need to do this only for importing file. This is something that should work automatically.
In your utils folder __init__.py should be blank. If this doesn't work, try adding from __future__ import absolute_import in your xyz.py file.
Check your current directory. It must be main_directory.
import os
print("Current working directory is: ", os.getcwd()
if not, you can change using
os.chdir("path/to/main_directory")
also works with relative path
os.chdir('..')
I was also facing same problem when you use row python script so i use the following code at the beginning of the file
import os
import sys
current_dir = os.path.dirname(os.path.realpath(__file__))
parent_dir = os.path.dirname(current_dir)
sys.path.append(parent_dir)
This way it will search the require file at parent directory.
Hope this will work for you also..
You could move your utils folder into drivers, making the path to the to-be imported file a subdirectory of your executing file, like:
main_directory/drivers/utils/connect.py
Alternatively, you could try
from ..utils import connect as dc
This will move up a directory before import.
Lasty, you could add the directory to Path in your script via
import sys
sys.path.insert(0,'/path/to/mod_directory')
For this method, see also this question

Relative imports - ModuleNotFoundError: No module named x

This is the first time I've really sat down and tried python 3, and seem to be failing miserably. I have the following two files:
test.py
config.py
config.py has a few functions defined in it as well as a few variables. I've stripped it down to the following:
config.py
debug = True
test.py
import config
print (config.debug)
I also have an __init__.py
However, I'm getting the following error:
ModuleNotFoundError: No module named 'config'
I'm aware that the py3 convention is to use absolute imports:
from . import config
However, this leads to the following error:
ImportError: cannot import name 'config'
So I'm at a loss as to what to do here... Any help is greatly appreciated. :)
TL;DR: You can't do relative imports from the file you execute since __main__ module is not a part of a package.
Absolute imports - import something available on sys.path
Relative imports - import something relative to the current module, must be a part of a package
If you're running both variants in exactly the same way, one of them should work. Here is an example that should help you understand what's going on. Let's add another main.py file with the overall directory structure like this:
.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py
And let's update test.py to see what's going on:
# config.py
debug = True
# test.py
print(__name__)
try:
# Trying to find module in the parent package
from . import config
print(config.debug)
del config
except ImportError:
print('Relative import failed')
try:
# Trying to find module on sys.path
import config
print(config.debug)
except ModuleNotFoundError:
print('Absolute import failed')
# main.py
import ryan.test
Let's run test.py first:
$ python ryan/test.py
__main__
Relative import failed
True
Here "test" is the __main__ module and doesn't know anything about belonging to a package. However import config should work, since the ryan folder will be added to sys.path.
Let's run main.py instead:
$ python main.py
ryan.test
True
Absolute import failed
And here test is inside of the "ryan" package and can perform relative imports. import config fails since implicit relative imports are not allowed in Python 3.
Hope this helped.
P.S.: If you're sticking with Python 3 there is no more need for __init__.py files.
You have to append your project's path to PYTHONPATH and make sure to use absolute imports.
For UNIX (Linux, OSX, ...)
export PYTHONPATH="${PYTHONPATH}:/path/to/your/project/"
For Windows
set PYTHONPATH=%PYTHONPATH%;C:\path\to\your\project\
Absolute imports
Assuming that we have the following project structure,
└── myproject
├── mypackage
│ ├── __init__.py
│ ├── a.py
└── anotherpackage
├── __init__.py
├── b.py
├── c.py
└── mysubpackage
├── __init__.py
└── d.py
just make sure to reference each import starting from the project's root directory. For instance,
# in module a.py
import anotherpackage.mysubpackage.d
# in module b
import anotherpackage.c
import mypackage.a
For a more comprehensive explanation, refer to the article How to fix ModuleNotFoundError and ImportError
I figured it out. Very frustrating, especially coming from python2.
You have to add a . to the module, regardless of whether or not it is relative or absolute.
I created the directory setup as follows.
/main.py
--/lib
--/__init__.py
--/mody.py
--/modx.py
modx.py
def does_something():
return "I gave you this string."
mody.py
from modx import does_something
def loaded():
string = does_something()
print(string)
main.py
from lib import mody
mody.loaded()
when I execute main, this is what happens
$ python main.py
Traceback (most recent call last):
File "main.py", line 2, in <module>
from lib import mody
File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
from modx import does_something
ImportError: No module named 'modx'
I ran 2to3, and the core output was this
RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
## -1,4 +1,4 ##
-from modx import does_something
+from .modx import does_something
def loaded():
string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py
I had to modify mody.py's import statement to fix it
try:
from modx import does_something
except ImportError:
from .modx import does_something
def loaded():
string = does_something()
print(string)
Then I ran main.py again and got the expected output
$ python main.py
I gave you this string.
Lastly, just to clean it up and make it portable between 2 and 3.
from __future__ import absolute_import
from .modx import does_something
Setting PYTHONPATH can also help with this problem.
Here is how it can be done on Windows
set PYTHONPATH=.
You can simply add following file to your tests directory, and then python will run it before the tests
__init__.py file
import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
Set PYTHONPATH environment variable in root project directory.
Considering UNIX-like:
export PYTHONPATH=.
Tried your example
from . import config
got the following SystemError:
/usr/bin/python3.4 test.py
Traceback (most recent call last):
File "test.py", line 1, in
from . import config
SystemError: Parent module '' not loaded, cannot perform relative import
This will work for me:
import config
print('debug=%s'%config.debug)
>>>debug=True
Tested with Python:3.4.2 - PyCharm 2016.3.2
Beside this PyCharm offers you to Import this name.
You hav to click on config and a help icon appears.
If you are using python 3+ then try adding below lines
import os, sys
dir_path = os.path.dirname(os.path.realpath(__file__))
parent_dir_path = os.path.abspath(os.path.join(dir_path, os.pardir))
sys.path.insert(0, parent_dir_path)
Declare correct sys.path list before you call module:
import os, sys
#'/home/user/example/parent/child'
current_path = os.path.abspath('.')
#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)
sys.path.append(parent_path)
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'child.settings')
I am working in a Linux machine. I had the same issue when I run python my_module/__main__.py.
The error is fixed, if you run the command export PYTHONPATH=. before your run your script.
export PYTHONPATH=.
python my_module/__main__.py
Try
from . import config
What that does is import from the same folder level. If you directly try to import it assumes it's a subordinate
This example works on Python 3.6.
I suggest going to Run -> Edit Configurations in PyCharm, deleting any entries there, and trying to run the code through PyCharm again.
If that doesn't work, check your project interpreter (Settings -> Project Interpreter) and run configuration defaults (Run -> Edit Configurations...).
As was stated in the comments to the original post, this seemed to be an issue with the python interpreter I was using for whatever reason, and not something wrong with the python scripts. I switched over from the WinPython bundle to the official python 3.6 from python.org and it worked just fine. thanks for the help everyone :)
You may use these statements to set the working directory, which worked for me with python3
import os
import sys
sys.path.insert(1, os.getcwd())
For me, simply adding the current directory worked.
Using the following structure:
└── myproject
├── a.py
└── b.py
a.py:
from b import some_object
# returns ModuleNotFound error
from myproject.b import some_object
# works
In my experience, PYTHONPATH environment variable does not work everytime.
In my case, my pytest only worked when I added the absolute path:
sys.path.insert(
0, "/Users/bob/project/repo/lambda"
)
I see many answers importing sys and os. Here's a not mentioned yet shorter one that GitHub Copilot gave me:
import sys
sys.path.append(__file__.rsplit("/", 1)[0])
Adding this to the top of my python script solved the problem as well.
To have Bash automatically recognise the project dir you're in:
sudo nano ~/.bashrc
OR
sudo nano ~/.bash_profile
At the bottom of the bash file:
function set_pythonpath {
export PYTHONPATH="$(pwd):$PYTHONPATH"
}
PROMPT_COMMAND=set_pythonpath
To save and exit:
Ctrl + X
Y
Test your changes by:
cat ~/.bashrc

Python: ImportError happens on IDE suggestion

This is my packages structure:
This is my __init.py__ inside settings package:
from settings import *
This is my functions.py:
from git import *
import initializer.settings as settings
_repo_remote = "https://%s:%s#%s" % (settings.git_username, settings.git_password, git_info["remote"])
Although I imported the settings package with my IDE auto-complete, I keep getting:
ImportError: No module named initializer.settings
When changing my import to:
import settings
The code works, but IDE is showing an error, why does it happen and what's wrong? I assume it is something with the path it try to load the module from, but I don't know how to change or control it..
If your main.py is in the 'initializer' folder (it appears to be?), you could import simply like this instead:
import settings
As long as the __init__.py in the 'settings' folder is like you described it. You would need to have the 'main.py' in the topmost folder to use it as you had it.

how to import module in upper directory in python

I have several python modules in the project and I put them in different folders, for example,
pythonProject\folderA\modulex.py
pythonProject\folderB\moduley.py
pythonProject\commonModule\module1.py
I have __init__.py in each folder.
In this situation, how can I import module1 into modulex?
Use relatively import
# in modulex
from ..commonModule import module1
Whenever you have python packages (those folders that contain __init__.py files), you can import the modules like below
modulex.py
----------
from pythonproject.commonModule import module1
Try this, If the pythonproject is not defined by the tool, then you could use the relative addressing like below
from ..commonModule import module1
The best if all modules are in the same directory. In case any of them in different possible use of os.chdir(path). With os.chdir(path) method (https://docs.python.org/3.2/library/os.html) possible change working directory in your program.
import os
import modulex
#assume working directory is "pythonProject\folderA\"
os.chdir(r'pythonProject\commonModule\')
#now working directory is "pythonProject\commonModule\"
import module1

python unable to import module

I have my program set up using packages as followed:
-base
-init.py
-base_class.py
-test
-init.py
-test.py
When I do the import statement from base.base_class import BaseClass in the test.py I get this error when running it:
from base.base_class import BaseClass
ImportError: No module named base.base_class
How can I import this module?
at the top of test.py add
import sys
sys.path.append("..")
base is not a folder on the path...once you change this it should work
or put test.py in the same folder as base. or move base to somewhere that is on your path
you nee to have an __init__.py file in each folder you import from
You have to create a file called "__init__.py" at python directories, then "the Python" will understand that directory as a Python package.
there are 3 things you can do:
add an init.py file to each folder
add sys.path.append("Folder") to the top
or use imp and do;
import imp
foo = imp.load_source('filename', 'File\Directory\filename.py')
then foo will be the name of the module for example foo.method()

Categories

Resources