This is a very typical issue, so I will leave this here for future reference.
If I have a project called: my_project
.
βββ my_project
βββ first_folder
βββ second_folder
βββ third_folder
What you want to do is one of these two things:
- PYTHONPATH (only Python)
cd ~/my_project && export PYTHONPATH=$(pwd)
change dir to root dir, and export that dir to PYTHONPATH, so when Python runs it looks in the PYTHONPATH.
- PATH (everything)
cd ~/my_project && export PATH=$PATH:$(pwd)
Same as above!
This needed to live somewhere since it took me a while to figure out. So for anyone in the future who needs help with this!
Answer from DUDANF on Stack OverflowThis is a very typical issue, so I will leave this here for future reference.
If I have a project called: my_project
.
βββ my_project
βββ first_folder
βββ second_folder
βββ third_folder
What you want to do is one of these two things:
- PYTHONPATH (only Python)
cd ~/my_project && export PYTHONPATH=$(pwd)
change dir to root dir, and export that dir to PYTHONPATH, so when Python runs it looks in the PYTHONPATH.
- PATH (everything)
cd ~/my_project && export PATH=$PATH:$(pwd)
Same as above!
This needed to live somewhere since it took me a while to figure out. So for anyone in the future who needs help with this!
Check the python version you are calling. Run "python --version". If it's not 3.7.1, that's the problem. If it returns a version beginning with "2", then try running the python3 binary instead.
Python: No module found even though it exists in directory - Stack Overflow
Improve ModuleNotFoundError to cater for condition when directory exists
Python doesn't find local module although it is installed and its location exists in sys.path
python - 'ModuleNotFoundError' when trying to import module from imported package - Stack Overflow
All modules in Python have to have a certain directory structure. You can find details here.
Create an empty file called __init__.py under the model directory, such that your directory structure would look something like that:
.
βββ project
βββ src
βββ hello-world.py
βββ model
βββ __init__.py
βββ order.py
Also in your hello-world.py file change the import statement to the following:
from model.order import SellOrder
That should fix it
P.S.: If you are placing your model directory in some other location (not in the same directory branch), you will have to modify the python path using sys.path.
If it's your root module, just add it to PYTHONPATH (PyCharm usually does that):
export PYTHONPATH=$PYTHONPATH:<root module path>
For Docker:
ENV PYTHONPATH="${PYTHONPATH}:<root module path in container>"
Three possibilities come to my mind:
- The module just works for certain python versions (e.g. 3.5 but not 3.6).
- The path where your module is currently located does not appear in sys.path.
- The class you want to use must be specified while importing the module because it is not specified in the __init__.py of the module itself.
As far as I can tell, only the first option might cause your problem.
Nevertheless I would make a quick check with
import sys
sys.path
and in case that the correct path is really missing..
sys.path.append('PathToModule')
You will need to do a relative import (PEP-328), but according to this guide, you can only go up until the level where you launched the script from, which is the tests directory in you case.
So you'll either have to add the model directory to the path, or add the source folder of your project to a .pth file in your site-packages as shown here
FIRST, if you want to be able to access man1.py from man1test.py AND manModules.py from man1.py, you need to properly setup your files as packages and modules.
Packages are a way of structuring Pythonβs module namespace by using βdotted module namesβ. For example, the module name
A.Bdesignates a submodule namedBin a package namedA....
When importing the package, Python searches through the directories on
sys.pathlooking for the package subdirectory.The
__init__.pyfiles are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such asstring, from unintentionally hiding valid modules that occur later on the module search path.
You need to set it up to something like this:
man
|- __init__.py
|- Mans
|- __init__.py
|- man1.py
|- MansTest
|- __init__.py
|- SoftLib
|- Soft
|- __init__.py
|- SoftWork
|- __init__.py
|- manModules.py
|- Unittests
|- __init__.py
|- man1test.py
SECOND, for the "ModuleNotFoundError: No module named 'Soft'" error caused by from ...Mans import man1 in man1test.py, the documented solution to that is to add man1.py to sys.path since Mans is outside the MansTest package. See The Module Search Path from the Python documentation. But if you don't want to modify sys.path directly, you can also modify PYTHONPATH:
sys.pathis initialized from these locations:
- The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH(a list of directory names, with the same syntax as the shell variablePATH).- The installation-dependent default.
THIRD, for from ...MansTest.SoftLib import Soft which you said "was to facilitate the aforementioned import statement in man1.py", that's now how imports work. If you want to import Soft.SoftLib in man1.py, you have to setup man1.py to find Soft.SoftLib and import it there directly.
With that said, here's how I got it to work.
man1.py:
from Soft.SoftWork.manModules import *
# no change to import statement but need to add Soft to PYTHONPATH
def foo():
print("called foo in man1.py")
print("foo call module1 from manModules: " + module1())
man1test.py
# no need for "from ...MansTest.SoftLib import Soft" to facilitate importing..
from ...Mans import man1
man1.foo()
manModules.py
def module1():
return "module1 in manModules"
Terminal output:
$ python3 -m man.MansTest.Unittests.man1test
Traceback (most recent call last):
...
from ...Mans import man1
File "/temp/man/Mans/man1.py", line 2, in <module>
from Soft.SoftWork.manModules import *
ModuleNotFoundError: No module named 'Soft'
$ PYTHONPATH=$PYTHONPATH:/temp/man/MansTest/SoftLib
$ export PYTHONPATH
$ echo $PYTHONPATH
:/temp/man/MansTest/SoftLib
$ python3 -m man.MansTest.Unittests.man1test
called foo in man1.py
foo called module1 from manModules: module1 in manModules
As a suggestion, maybe re-think the purpose of those SoftLib files. Is it some sort of "bridge" between man1.py and man1test.py? The way your files are setup right now, I don't think it's going to work as you expect it to be. Also, it's a bit confusing for the code-under-test (man1.py) to be importing stuff from under the test folder (MansTest).
I had a similar problem, although not the same.
My folders and files had the structure (GUI_ML is the main folder):
GUI_ML
\ Views \ login.py
\ Views \ __ init __.py
\ Controllers \ Control_login.py
\ Controllers \ __ init __.py
I needed to import Control_login.py from login.py. The following code solved my problem:
import sys
import os
myDir = os.getcwd()
sys.path.append(myDir)
from pathlib import Path
path = Path(myDir)
a=str(path.parent.absolute())
sys.path.append(a)
from Controllers.Control_login import Control_login
Hey Guys,
I get a weird ModuleNotFoundError in one of my projects and i do not really understand why. So here is my Folder Structure:
Project\
| main.py
| packageabc\
| | __init__.py
| | abc.py
| | packagexyz\
| | | xyz.py
In every .py file is an abc/xyz or main class. Now the interesting part. Inside the abc.py I do an import like this:
from packagexyz.xyz import xyz
This works perfectly fine!
Inside the main.py I do an import like this:
from packageabc.abcimport abc
Now I get an ModuleNotFoundError. Error Code looks like this:
from packagexyz.xyz import xyz ModuleNotFoundError: no module named packagexyz.
So the import in the abc.py File that works perfectly when tested inside the file does not work if the abc.py file is imported. So why is that?
Since the python interpreter is started within test, that's where it looks for imports. You can learn about pythons's search behavior for imports through the docs, if you're interested in the details.
To solve your problem, there are a bunch of ways to do it, the best one depending on how you plan to use your code. If you plan to write a library, it might make sense to package it, which would give you access to a global namespace that you can use.
But if you just want it to work right now, and only ever are going to run the interpreter from the same place (i.e. your test folder), defining the third file as a local one should do it:
second.py
from . import third
third.py
print('third here, not an import error')
This works for me:
~/test$ tree .
.
βββ first.py
βββ numpad
βββ second.py
βββ third.py
~/test$ python3.6 first.py
third here, not an import error
I might be wrong on this, but I'm pretty sure you'd have to set up your environment variable to look in that specific folder. Which would be way more of a hassle than just adding your homemade modules to your default modules folder.
for me its working and on linux too.
ο [~/Alexzander__/programming/python3/learning/modulenotfounderror]
β± tree
ο .
βββ ξ main.py
βββ ο utils
βββ ξ forms.py
ο [~/Alexzander__/programming/python3/learning/modulenotfounderror]
β± ca main.py
from utils.forms import search_form
print("success")%
ο [~/Alexzander__/programming/python3/learning/modulenotfounderror]
β± python main.py
success
Create a file named __init__.py in the utils folder, which allows the folder to be used as a package. (The file doesn't have to have anything inside)
This is only necessary on python 2 though, in python 3 it works automatically without the need for such file.