Zelong
Zelong

Reputation: 2556

Correct way of "Absolute Import" in Python 2.7

The directory tree looks like:

Project/
    prjt/
        __init__.py
        pkg1/
            __init__.py
            module1.py
            tests/
                __init__.py
                test_module1.py
        pkg2/
            __init__.py
            module2.py
            tests/
                __init__.py
                test_module2.py
        pkg3/
            __init__.py
            module3.py
            tests/
                __init__.py
                test_module3.py
    data/
    log/

I tried to use the function compute() of pkg2/module2.py in pkg1/module1.py by writing like:

# In module1.py
import sys
sys.path.append('/path/to/Project/prjt')

from prjt.pkg2.module2 import compute

But when I ran python module1.py, the interpreter raised an ImportError that No module named prjt.pkg2.module2.

  1. What is the correct way of "absolute import"? Do I have to add the path to Project to sys.path?
  2. How could I run test_module1.py in the interactive interpreter? By python prjt/pkg1/tests/test_module1.py or python -m prjt/pkg1/tests/test_module1.py?

Upvotes: 27

Views: 8904

Answers (5)

Vasily Ryabov
Vasily Ryabov

Reputation: 9991

If you add sys.path.append('path/to/Project') into prjt/__init__.py, you need to import submodules so: from pkg2.module2 import compute (without prjt specification) because prjt package import is in progress and the higher level folder is not in the sys.path. This is exactly what @Cissoid suggested.

BTW, from __future__ import absolute_import is not necessary for Py >= 3.0.


Answering your second question... I have very similar structure for unittests subfolder, so in the pkg/unittests/testall.py I wrote the following:

testfolder = os.path.abspath(os.path.dirname(__file__))
project_root = os.path.abspath(os.path.join(testfolder, r"..\.."))
sys.path.append(project_root)
import pkg

I run it without -m option because it's unnecessary complication.

Upvotes: 7

FabienP
FabienP

Reputation: 3138

Using explicit relative imports, this should work from module1.py:

from ..pkg2.module2 import compute()

This is cleaner than messing with PYTHONPATH...

Upvotes: 0

Atul Jain
Atul Jain

Reputation: 1055

try this

import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

This will give absolute path

Upvotes: 2

Sean
Sean

Reputation: 3042

How python find module

python will find module from sys.path, and the first entry sys.path[0] is '' means, python will find module from the current working directory

import sys
print sys.path

and python find third-party module from site-packages

so to absolute import, you can

append your package to the sys.path

import sys
sys.path.append('the_folder_of_your_package')

import module_you_created

module_you_created.fun()

export PYTHONPATH

the PYTHONPATH will be imported into sys.path before execution

export PYTHONPATH=the_folder_of_your_package

import sys
[p for p in sys.path if 'the_folder_of_your_package' in p]

How could I run test_module1.py in the interactive interpreter? By python Project/pkg1/tests/test_module1.py or python -m Project/pkg1/tests/test_module1.py?

you can use if __name__ == '__main__': idiomatic way, and use python Project/pkg1/tests/test_module1.py

if __name__ = '__main__':
    main()

Upvotes: 15

Cissoid
Cissoid

Reputation: 81

Import the outer Project path.

sys.path.append('/path/to/Project')

Or import "compute" start from pkg2

from pkg2.module2 import compute

Upvotes: 6

Related Questions