0

I have the following directory tree:

project/
  A/
    __init__.py
    foo.py
  TestA/
    __init__.py
    testFoo.py

the content of testFoo is:

import unittest
from A import foo

from the project directory I run python testA/testFoo.py

I get a ModuleNotFoundError No module named A

I have two question: how to improt and run A.foo from TestA.testFoo and why is it so difficult to grasp the import logic in Python? Isn't there any debug trick to solve this kind of issues rapidly, I'm sorry I have to bother you with such basics questions?

jimifiki
  • 5,377
  • 2
  • 34
  • 60

5 Answers5

1

Add the folder project/testA to the system pythonpath first:

import sys
sys.path.insert(0, "/path/to/pythonfile")

and try the import again.

Shintlor
  • 742
  • 6
  • 19
  • 1
    This works but sounds like a horrible hack. Isn't it? – jimifiki Sep 03 '18 at 09:24
  • I think it is OK if you have to import something at runtime. If you want something more sophisticated or general, you should consider building your own package (which is a different question :) ) – Shintlor Sep 03 '18 at 09:53
1

When your are executing a file an environment variable called python path is generated, python import work with this variable to find your file to import, this path is generated with the path of the file you are executing and it will search in the current directory and sub directories containing an __init__.py file, if you want to import from a directory on the same level you need to modify your python path or change the architecture of your project so the file executed is always on top level.

you can include path to your python path like this :

import sys
sys.path.insert(0, "/path/to/file.py")

You can read more on import system : https://docs.python.org/3/reference/import.html

The best way in my opinion is to not touch the python path and include your test directoy into the directory where tested files are:

project/
  A/
    __init__.py
    foo.py
    TestA/
        __init__.py
        testFoo.py

Then run the python -m unittest command into your A or project directory, it will search into your current and sub directories for test and execute it.

More on unittest here : https://docs.python.org/3/library/unittest.html

bboumend
  • 490
  • 3
  • 13
  • I like the "move your test directory where the tested files are" way. But in testFoo I now include with 'from ..foo import ...' and I get the infamous "attempted relative import beyond top-level package" error. – jimifiki Sep 04 '18 at 07:35
  • You should consider using python unittest standard library and run your test with `python -m unittest` into your A directory. https://docs.python.org/3/library/unittest.html, also pytest is a realy good library for testing. – bboumend Sep 04 '18 at 09:27
1

Can you try this ?

Create an empty file __init__.py in subdirectory TestA. And add at the begin of main code

from __future__ import absolute_import

Then import as below :

import A.foo as testfoo
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Alex
  • 189
  • 4
  • 23
0

The recommended way in py3 may be like below

echo $pwd
$ /home/user/project
python -m testA.testFoo

The way of execute module python -m in python is a good way to replace relative references。

moonscar
  • 21
  • 2
0

You definitely cannot find A because python need look from sys.path, PYTHONPATH to find the module.

And python will automatically add current top level script to sys.path not currently directory to sys.path. So if you add print(sys.path) in testFoo.py, you will see it only add project/TestA to the sys.path.

Another word, the project did not be included in sys.path, then how python can find the module A?

So you had to add the project folder to sys.path by yourself, and, this just needed in top script, something like follows:

import unittest
import sys
import os
file_path = os.path.abspath(os.path.dirname(__file__)).replace('\\', '/')
lib_path = os.path.abspath(os.path.join(file_path, '..')).replace('\\', '/')
sys.path.append(lib_path)
atline
  • 28,355
  • 16
  • 77
  • 113