631 votes

Importer un fichier à partir d'un sous-répertoire ?

J'ai un fichier appelé tester.py situé sur /project .

/project a un sous-répertoire appelé lib avec un fichier appelé BoxTime.py :

/project/tester.py
/project/lib/BoxTime.py

Je veux importer BoxTime de tester . J'ai essayé ceci :

import lib.BoxTime

Ce qui a donné :

Traceback (most recent call last):
  File "./tester.py", line 3, in <module>
    import lib.BoxTime
ImportError: No module named lib.BoxTime

Une idée sur la façon d'importer BoxTime du sous-répertoire ?

EDITAR

En __init__.py était le problème, mais n'oubliez pas de vous référer à BoxTime comme lib.BoxTime ou l'utiliser :

import lib.BoxTime as BT
...
BT.bt_function()

1 votes

Il semble qu'il importe lib/BoxTime à tester .

680voto

Greg Points 2980

Jetez un coup d'œil à la Documentation sur les paquets (section 6.4) .

En bref, vous devez mettre un fichier vide nommé

__init__.py

dans le lib répertoire.

81 votes

Pourquoi est-ce que ça fait hacky ? C'est la façon dont python marque les répertoires d'importation sûrs/disponibles.

12 votes

Non seulement il marque les répertoires d'importation sûrs/disponibles, mais il fournit également un moyen d'exécuter un certain code d'initialisation lors de l'importation d'un nom de répertoire.

53 votes

Oui, c'est un peu compliqué et même sale, et à mon avis, le langage ne devrait pas imposer sa façon de charger les fichiers à travers le système de fichiers. En PHP, nous avons résolu le problème en laissant le code utilisateur enregistrer plusieurs fonctions de chargement automatique qui sont appelées lorsqu'un espace de noms/une classe est manquant(e). Ensuite, la communauté a produit la norme PSR-4 et Composer l'implémente, et aujourd'hui personne n'a à s'inquiéter de cela. Et pas de code dur stupide __init__ (mais si vous le voulez, il suffit d'enregistrer un hook d'autoloading ! C'est la différence entre hacky y piratable ).

219voto

hughdbrown Points 15770
  • Créez un sous-répertoire nommé lib .

  • Créez un fichier vide nommé lib\__init__.py .

  • En lib\BoxTime.py écrire une fonction foo() comme ça :

    def foo():
        print "foo!"
  • Dans votre code client dans le répertoire ci-dessus lib , écrivez :

    from lib import BoxTime
    BoxTime.foo()
  • Exécutez votre code client. Vous obtiendrez :

    foo!

Beaucoup plus tard -- sous linux, ça ressemblerait à ça :

% cd ~/tmp
% mkdir lib
% touch lib/__init__.py
% cat > lib/BoxTime.py << EOF
heredoc> def foo():
heredoc>     print "foo!"
heredoc> EOF
% tree lib
lib
 BoxTime.py
 __init__.py

0 directories, 2 files
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from lib import BoxTime
>>> BoxTime.foo()
foo!

2 votes

Pourriez-vous fournir un lien vers la documentation Python où cela est expliqué ? Merci !

5 votes

Faisons en sorte que ce lien soit cliquable : docs.python.org/3/tutorial/modules.html#packages

0 votes

Un guide pratique pour la mise en œuvre d'un paquet lib

97voto

Kresimir Points 81

Vous pouvez essayer de l'insérer dans sys.path :

sys.path.insert(0, './lib')
import BoxTime

16 votes

C'est idéal si, pour une raison ou une autre, vous ne pouvez pas ou ne voulez pas créer le fichier init fichier .py.

5 votes

Cela fonctionne si vous exécutez python depuis le répertoire "project". Le "." est interprété par rapport à votre répertoire de travail actuel, et non par rapport au répertoire où se trouve le fichier que vous exécutez. Disons que vous cd /data , python ../project/tester.py . Alors ça ne marchera pas.

2 votes

Cela a marché pour moi. Je préfère cela à un init .py, cela rend les déclarations d'importation plus propres.

28voto

spatz Points 4081

Essayez import .lib.BoxTime . Pour plus d'informations, lisez l'article sur l'importation relative dans PEP 328 .

2 votes

Je ne pense pas avoir déjà vu cette syntaxe utilisée auparavant. Y a-t-il une bonne raison (ou non) d'utiliser cette méthode ?

2 votes

Pourquoi ce n'était pas la réponse. Bien sûr, si tu veux faire le truc des paquets, tu devrais le faire. Mais ce n'est pas ce que la question originale était.

0 votes

Cela me donne : ValueError : Tentative d'importation relative dans un non-paquet

20voto

Wade Points 692

Votre répertoire lib contient-il un __init__.py fichier ?

Python utilise __init__.py pour déterminer si un répertoire est un module.

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