1043 votes

Importation de modules à partir du dossier parent

J'utilise Python 2.5.

Voici mon arbre à dossiers :

ptdraft/
  nib.py
  simulations/
    life/
      life.py

(J'ai aussi __init__.py dans chaque dossier, omis ici pour des raisons de lisibilité)

Comment importer le nib à partir de l'intérieur du module life module ? J'espère qu'il est possible de le faire sans bricoler avec sys.path.

Remarque : le module principal en cours d'exécution se trouve dans la section ptdraft dossier.

1 votes

Quel est le réglage de votre PYTHONPATH ?

2 votes

Ross : J'ai regardé là. Qu'est-ce que je devrais faire ? J'ai déjà un __init__.py . S.Lott : Je ne sais pas comment vérifier...

4 votes

Echo $PYTHONPATH depuis le shell ; import sys ; print sys.path depuis Python. docs.python.org/tutorial/

741voto

f3lix Points 13634

Vous pouvez utiliser les importations relatives (python >= 2.5) :

from ... import nib

(Quoi de neuf dans Python 2.5) PEP 328 : Importations absolues et relatives

EDIT : ajout d'un autre point '.' pour remonter de deux paquets

299 votes

ValueError: Attempted relative import in non-package

24 votes

@endolith : Vous devez être dans un paquet, c'est-à-dire que vous devez avoir une init fichier .py.

60 votes

Tentative d'importation relative au-delà du paquet de niveau supérieur

461voto

Remi Points 4223

Importations relatives (en from .. import mymodule ) ne fonctionnent que dans un paquet. Pour importer 'mymodule' qui se trouve dans le répertoire parent de votre module actuel :

import os
import sys
import inspect

currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
sys.path.insert(0, parentdir) 

import mymodule

modifier : le __file__ n'est pas toujours donné. Au lieu d'utiliser os.path.abspath(__file__) J'ai maintenant suggéré d'utiliser le module inspect pour récupérer le nom de fichier (et le chemin) du fichier actuel

186 votes

Quelque chose d'un peu plus court : sys.path.insert(1, os.path.join(sys.path[0], '..'))

9 votes

Y a-t-il une raison d'éviter sys.path.append() au lieu de l'insert ?

3 votes

@Tyler - Cela peut avoir de l'importance si quelque part ailleurs alors la parentdir mais dans l'un des chemins déjà spécifiés dans le document sys.path il y a un autre module avec le nom 'mymodule'. En insérant le module parentdir comme premier élément du sys.path garantit que le module de parentdir sera importé à la place.

153voto

hasenj Points 36139

Il semble que le problème ne soit pas lié au fait que le module se trouve dans un répertoire parent ou autre.

Vous devez ajouter le répertoire qui contient ptdraft à PYTHONPATH

Vous avez dit que import nib a travaillé avec vous, cela signifie probablement que vous avez ajouté ptdraft lui-même (et non son parent) à PYTHONPATH.

62 votes

Le fait de devoir tout ajouter à pythonpath n'est pas une bonne solution si vous travaillez avec un grand nombre de paquets qui ne seront jamais réutilisés.

5 votes

@JasonCheng : Alors pourquoi sont-ils paquets ?

17 votes

Pour moi, cette réponse a fonctionné. Cependant, pour être plus explicite, la procédure est la suivante import sys et ensuite sys.path.append("..\<parent_folder>")

65voto

Ricardo Murillo Points 634

Si l'ajout du dossier de votre module au PYTHONPATH n'a pas fonctionné, vous pouvez modifier le fichier de configuration du module. sys.path dans votre programme, où l'interpréteur Python recherche les modules à importer, l'option documentation python dit :

Lorsqu'un module nommé spam est importé, l'interpréteur recherche d'abord un module intégré portant ce nom. S'il ne le trouve pas, il cherche alors un fichier nommé spam.py dans une liste de répertoires donnée par la variable sys.path. sys.path est initialisé à partir de ces emplacements :

  • le répertoire contenant l'entrée script (ou le répertoire courant).
  • PYTHONPATH (une liste de noms de répertoires, avec la même syntaxe que la variable shell PATH).
  • la valeur par défaut dépendant de l'installation.

Après l'initialisation, les programmes Python peuvent modifier sys.path . Le répertoire contenant le script en cours d'exécution est placé au début du chemin de recherche, avant le chemin de la bibliothèque standard. Cela signifie que les scripts de ce répertoire seront chargés à la place des modules du même nom dans le répertoire de la bibliothèque. Il s'agit d'une erreur, sauf si le remplacement est prévu.

Sachant cela, vous pouvez faire ce qui suit dans votre programme :

import sys
# Add the ptdraft folder path to the sys.path list
sys.path.append('/path/to/ptdraft/')

# Now you can import your module
from ptdraft import nib
# Or just
import ptdraft

8 votes

Votre réponse est bonne, mais ne fonctionne pas toujours et n'est pas très portable. Si le programme a été déplacé vers un nouvel emplacement, /path/to/ptdraft devra être modifié. Il existe des solutions qui permettent de déterminer le répertoire actuel du fichier et de l'importer depuis le dossier parent de cette façon également.

1 votes

@Edward : quelles sont ces techniques ?

1 votes

@Shuklaswag par exemple, la réponse stackoverflow.com/questions/714063/ .

34voto

Mike Points 549

Voici une solution plus générique qui inclut le répertoire parent dans sys.path (fonctionne pour moi) :

import os.path, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))

0 votes

import os, sys\n sys.path.insert(0,os.path.pardir) même chose, mais plus trivial :) (pas de flux de ligne dans les commentaires)

0 votes

@antiveeranna, si vous utilisez os.path.pardir vous n'obtiendrez pas le chemin réel du parent, mais seulement le chemin relatif à partir de l'endroit où vous appelez la fonction sys.path.insert()

2 votes

Cette réponse utilise le __file__ variable qui peut être peu fiable (il ne s'agit pas toujours du chemin d'accès complet au fichier, il ne fonctionne pas sur tous les systèmes d'exploitation, etc. Modifier la réponse pour ne pas l'inclure causera moins de problèmes et sera plus compatible avec les autres systèmes. Pour plus d'informations, voir stackoverflow.com/a/33532002/3787376 .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X