I'm using Python 3.7.1 on macOS Mojave Version 10.14.1
This is my directory structure:
man/ Mans/ man1.py MansTest/ SoftLib/ Soft/ SoftWork/ manModules.py Unittests/ man1test.py
man1.py contains the following import statement, which I do not want to change:
from Soft.SoftWork.manModules import *
man1test.py contains the following import statements:
from ...MansTest.SoftLib import Soft from ...Mans import man1
I need the second import in
man1test.py needs access to a function in
My rationale behind the first import (Soft) was to facilitate the aforementioned import statement in
Contrary to my expectation, however, the import statement in
man1.py gives rise to:
ModuleNotFoundError: No module named 'Soft'
when I run
python3 -m man.MansTest.Unittests.man1test
from a directory above man/.
Is there any way to resolve this error without changing the import statement in
man1.py and without adding anything to sys.path?
python3 -m man.ManTest.Unittests.man1test from the original version of the question changed to
python3 -m man.MansTest.Unittests.man1test
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 named
Bin a package named
When importing the package, Python searches through the directories on
sys.pathlooking for the package subdirectory.
__init__.pyfiles are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as
string, 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
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 variable
- The installation-dependent default.
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.
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())
# no need for "from ...MansTest.SoftLib import Soft" to facilitate importing.. from ...Mans import man1 man1.foo()
def module1(): return "module1 in manModules"
$ 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).
For me when I created a file and saved it as python file, I was getting this error during importing. I had to create a filename with the type ".py" , like filename.py and then save it as a python file. post trying to import the file worked for me.