web-dev-qa-db-fra.com

Méthode correcte "Importation absolue" dans Python 2.7

  • Python 2.7.10
  • Dans virtualenv
  • Activer from __future__ import absolute_import dans chaque module

L'arborescence de répertoires ressemble à:

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/

J'ai essayé d'utiliser la fonction compute() de pkg2/module2.py dans pkg1/module1.py en écrivant comme:

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

from prjt.pkg2.module2 import compute

Mais quand j'ai exécuté python module1.py, l'interpréteur a généré une ImportError qui No module named prjt.pkg2.module2.

  1. Quelle est la bonne manière d '"importation absolue"? Dois-je ajouter le chemin de Project à sys.path?
  2. Comment pourrais-je exécuter test_module1.py dans l'interpréteur interactif? Par python prjt/pkg1/tests/test_module1.py ou python -m prjt/pkg1/tests/test_module1.py?
27
Zelong

Comment trouver le module python

python trouvera le module dans sys.path, et la première entrée sys.path[0] est '' signifie que python trouvera le module dans le répertoire de travail actuel

import sys
print sys.path

et python recherchent un module tiers à partir de site-packages

donc à l'importation absolue, vous pouvez

ajoute votre paquet au sys.path

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

import module_you_created

module_you_created.fun()

export PYTHONPATH

le PYTHONPATH sera importé dans sys.path avant l'exécution

export PYTHONPATH=the_folder_of_your_package

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

Comment puis-je exécuter test_module1.py dans l'interpréteur interactif? Par python Projet/pkg1/tests/test_module1.py ou python -m Projet/pkg1/tests/test_module1.py?

vous pouvez utiliser if __== '__main__': de manière idiomatique et utiliser python Project/pkg1/tests/test_module1.py

if __= '__main__':
    main()
15
Sean

Importez le chemin de projet externe.

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

Ou importer "compute" à partir de pkg2

from pkg2.module2 import compute
6
Cissoid

Si vous ajoutez sys.path.append('path/to/Project') dans prjt/__init__.py, vous devez importer les sous-modules ainsi: from pkg2.module2 import compute (sans la spécification prjt) car l’importation de package prjt est en cours et le dossier de niveau supérieur ne se trouve pas dans le sys.path. C'est exactement ce que @Cissoid a suggéré.

BTW, from __future__ import absolute_import n'est pas nécessaire pour Py> = 2.6.


Répondant à votre deuxième question ... La structure du sous-dossier unittests est très similaire. C'est pourquoi, dans le pkg/unittests/testall.py, j'ai écrit ce qui suit:

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

Je le lance sans l'option -m parce que c'est une complication inutile.

6
Vasily Ryabov

essaye ça 

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

Cela donnera un chemin absolu 

2
Atul Jain

En utilisant des importations relatives explicites, cela devrait fonctionner à partir de module1.py:

from ..pkg2.module2 import compute()

C’est plus propre que de jouer avec PYTHONPATH...

0
FabienP