Python not finding modules that I have added to PYTHONPATH? - python

My file structure looks like this:
main
--src_module
----__init__.py
----utils.py
----tests
------test.py
PYTHONPATH looks like: '/Users/myName/main/src_module'
test.py has the line:
from src_module.utils import something
but when I try to run python test.py, I get the following error:
ImportError: No module named src_module.utils
I was under the impression that adding the src_module folder to PYTHONPATH would fix this problem, but clearly it hasn't. Can someone explain to me why I'm still experiencing these import errors?

You can access the utils.py file from tests directory with this structure.
main
--src_module
----__init__.py
----utils.py
--tests
----__init__.py
----test.py
Also you can use a test runner like nose2 to run your tests with command nose2 or if you would like to run the test.py file by itself then you can run via
python -m tests.test

Related

No module named 'backend' [pytest coverage]

I have a structure like this:
myProj
--backend
--app.py
--tests
--test_app.py
When i run the command:
pytest -v --cov=.tests/test_app
I get:
tests/test_app.py:1: in <module>
from backend.app import soma
E ModuleNotFoundError: No module named 'backend'
Why can't import the library?
When the structure like this:
myProj
--app.py
--test_app.py
Perform correctly.
How can i run coverage in my project with the first showed structure ?
This is because backend is not a package.
To make it work as a package you should create an empty file named __init__.py inside the backend folder, so it will work as expected.
To read more about how packages work in Python, check the documentation.
The problem here is the code structure and making a folder as a module so that it can be imported.
To make any folder work as module, we need to keep __init__.py file(empty or with some data to initialise) inside it. And while importing it make sure it's accessible from that file. i.e. either it is in the same directory or in the exported PYTHONPATH.
Consider following structure:
-- backend:
__init__.py
app.py
-- tests:
__init__.py
main.py
Here backend and tests are the directories and if you want to import something in main.py file from the app.py file it will go like following:
from ..backend.app import soma
Note the extra .. before backend module in above import line that helps the Python interpreter to find the soma from backend/app.py file.
As mentioned by #DiegoQueiroz and #HNMN3, you should make sure your directory as python package.
Add __init__.py file inside backend and tests directory.
Then, you need to mention module name in your command.
Given your project structure, you can input this command:
pytest -v --cov=backend.app tests/test_app

Module not found running on command line

I have the following project structure:
project/
example/
__init__.py
foo.py
boo.py
meh.py
tests/
example/
test_foo.py
test_boo.py
test_meh.py
As example, I'm importing foo.py in boo.py as import example.foo as f. And I'm running tests with python3 -m pytest -s -v --cov tests on root folder (project). The unit tests are running very smooth but when I try to run a single file as python3 example/boo.py I got an error:
ModuleNotFoundError: No module named 'example'
Modules inside a package shouldn't really be run (some exceptions).
But, you can set a PYTHONPATH before running the module if you really want. For a one off, use e.g.
PYTHONPATH=$(pwd) python3 example/boo.py
An alternative is to use relative imports: from . import foo as f inside boo.py. But that still implies that modules shouldn't really be run.
To elaborate a bit more:
A module should be imported, not run like a script. That is what a module is for. If, for some reason, you really really feel you need to execute module, then 1/ reconsider, 2/ rewrite your module, 3/ wrap a script around that module by calling the necessary function(s) inside the module (and keep the script itself relatively short).
Note that setuptools already has this functionality through entry points.
A simpler alternative is to use a proper
if __name__ == '__main__':
main()
line at the end of your module, where main() calls into your module functionality, then execute the module using the Python -m switch:
python -m mypackage.mymodule
But, again, try and limit this functionality.
It's usually a problem with environment variables. You can force the path using the following, and the import should work under all circumstances:
import sys
sys.path.append("/absolute/module/path")
import local_module

Python3 relative imports failing in package

I've been reading tons of questions related to this matter but none of the has help me so far. I'm currently using the Python click library to execute scripts as commands.
The current command that I'm trying to execute is placed inside a Python Package which has a __main__.py file, like the parent dir has. The current project structure is the following one.
/myproject
/foo_one
__init__.py
foo_one.py
/foo_two
__init__.py
foo_two.py
/foo_three
__init__.py
foo_three.py
/foo_four
__init__.py
foo_four.py
/foo_five
__init__.py
foo_five.py
/foo_six
__init__.py
foo_six.py
__init__.py
__main__.py
foo_seven.py
Whenever I try to run the __main__.py script located in the project folder, the following error comes up.
ModuleNotFoundError: No module named '__main__.foo_two'; '__main__' is not a package
However, if I try to execute that same script from a folder above with the -m option like this python3 myproject -m, the following is shown up.
ImportError: attempted relative import with no known parent package
The __main__.py has 2 imports like this... The __init__.py is empty.
from .foo_two.foo_two import AClass, AnotherClass, OtherClass
from .foo_three.foo_three import AnotherClassMore
UPDATE: Correcting the syntax error in a previous command, while calling python -m myproject gives me a ModuleNotFoundError because of a module that isn't my responsibility, which is basically a library that is used in the project.
Hopefully, this will be of value to someone out there - I went through half a dozen stackoverflow posts trying to figure out relative imports similar to whats posted above here. I set up everything as suggested but I was still hitting ModuleNotFoundError: No module named 'my_module_name'
Since I was just developing locally and playing around, I hadn't created/run a setup.py file. I also hadn't apparently set my PYTHONPATH.
I realized that when I ran my code as I had been when the tests were in the same directory as the module, I couldn't find my module:
$ python3 test/my_module/module_test.py 2.4.0
Traceback (most recent call last):
File "test/my_module/module_test.py", line 6, in <module>
from my_module.module import *
ModuleNotFoundError: No module named 'my_module'
However, when I explicitly specified the path things started to work:
$ PYTHONPATH=. python3 test/my_module/module_test.py 2.4.0
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s
OK
So, in the event that anyone has tried a few suggestions, believes their code is structured correctly and still finds themselves in a similar situation as myself try either of the following if you don't just add your export the current directory to your PYTHONPATH:
Run your code and explicitly include the path like so:
$ PYTHONPATH=. python3 test/my_module/module_test.py
To avoid calling PYTHONPATH=., create a setup.py file with contents like the following and run python setup.py development to add packages to the path:
# setup.py
from setuptools import setup, find_packages
setup(
name='sample',
packages=find_packages()
)
The correct syntax would be
python -m myproject
This should execute __main__ in the top-level package.
You need to have __init__.py in each sub folder with python code to tell the interpreter to treat the folder as a module
/myproject
/foo_one
__init__.py # add this
foo_one.py
/foo_two
__init__.py # add this
foo_two.py
/foo_three
__init__.py # add this
foo_three.py
/foo_four
__init__.py # add this
foo_four.py
/foo_five
__init__.py # add this
foo_five.py
/foo_six
__init__.py # add this
foo_six.py
__init__.py
__main__.py
foo_seven.py
the __init__.py is telling the interpreter to treat sub folders as python modules / packages and you should be able to import
The __init__.py file can be empty but needs to be present in the sub folders to be able to import that module / package

ImportError on console but not in PyCharm

I have the folowing dir structure
|population_model
--|__init__.py
--|run.py
inside __init__.py I have the following:
def my_func():
...
return
on run.py I have
from population_model import my_func
When I run the project from inside PyCharmthe code runs beautifully.
But when running from Terminal:
my/path/to/population_model/python run.py
I get ImportError: No module named population_model
What might be the cause?
Most likely PyCharm's Run configuration is setting the Working Directory to your project, where it can find population_model. In the terminal, cd to the directory first.

Python importing works from one folder but not another

I have a project directory that is set up in the following way:
>root
> modules
__init__.py
module1.py
> moduleClass
__init__.py
moduleClass1.py
moduleClass2.py
> scripts
runTests.py
> tests
__init__.py
test1.py
test2.py
run.sh
In runTests.py I have the following import statements:
import modules.module1
import modules.moduleClass.moduleClass2
import tests.test1
import tests.test2
The first two import statements work fine, but the second two give me the errors ImportError: No module named test1 and ImportError: No module named test2. I can't see what is different between the tests and modules directories.
I'd be happy to provide more information as needed.
When you run a script, Python adds the script's containing directory (here, scripts/) to sys.path. If your modules don't appear in sys.path any other way, that means Python may not be able to find them at all.
The usual solution is to put your scripts somewhere in your module hierarchy and "run" them with python -m path.to.module. But in this case, you could just use an existing test runner: Python comes with python -m unittest discover, or you might appreciate something fancier like py.test (pip install --user pytest).
The problem turned out to be that python didn't like the folder name tests. Changing the name to unit_tests solved the problem.

Categories

Resources