web-dev-qa-db-fra.com

Importations relatives - ModuleNotFoundError: Aucun module nommé x

C'est la première fois que je m'assieds vraiment et que j'essaie python 3, et que je semble échouer lamentablement. J'ai les deux fichiers suivants:

  1. test.py
  2. config.py

config.py a quelques fonctions définies ainsi que quelques variables. Je l'ai réduit à ce qui suit:

enter image description here

Cependant, j'obtiens l'erreur suivante:

ModuleNotFoundError: No module named 'config'

Je suis conscient que la convention py3 consiste à utiliser des importations absolues:

from . import config

Cependant, cela conduit à l'erreur suivante:

ImportError: cannot import name 'config'

Donc, je ne sais pas quoi faire ici ... Toute aide est grandement appréciée. :)

90
blitzmann

Comme indiqué dans les commentaires du message d'origine, cela semblait être un problème avec l'interprète python que j'utilisais pour une raison quelconque, et pas un problème avec les scripts python. Je suis passé du paquet WinPython au lot officiel python 3.6 de python.org et tout a bien fonctionné. Merci à tous pour l'aide :)

1
blitzmann

TL; DR: vous ne pouvez pas importer de données relatives à partir du fichier exécuter car le module __main__ ne fait pas partie d'un paquet.

Importations absolues - Importer quelque chose disponible sur sys.path

Importations relatives - importer quelque chose par rapport au module actuel, doit faire partie d'un package

Si vous utilisez les deux variantes exactement de la même manière, l'une d'entre elles devrait fonctionner. Quoi qu'il en soit, voici un exemple qui devrait vous aider à comprendre ce qui se passe, ajoutons un autre fichier main.py avec la structure de répertoires globale comme ceci:

.
./main.py
./ryan/__init__.py
./ryan/config.py
./ryan/test.py

Et mettons à jour test.py pour voir ce qui se passe:

# config.py
debug = True


# test.py
print(__name__)

try:
    # Trying to find module in the parent package
    from . import config
    print(config.debug)
    del config
except ImportError:
    print('Relative import failed')

try:
    # Trying to find module on sys.path
    import config
    print(config.debug)
except ModuleNotFoundError:
    print('Absolute import failed')


# main.py
import ryan.test

Lançons d'abord test.py:

$ python ryan/test.py
__main__
Relative import failed
True

Ici "test" est le module __main__ et ne sait rien de l'appartenance à un paquet. Cependant, import config devrait fonctionner, car le dossier ryan sera ajouté à sys.path.

Lançons main.py à la place:

$ python main.py
ryan.test
True
Absolute import failed

Et ici, le test se trouve à l'intérieur du paquet "ryan" et peut effectuer des importations relatives. import config échoue car les importations relatives implicites ne sont pas autorisées dans Python 3.

J'espère que cela a aidé.

P.S .: si vous vous en tenez à Python 3, les fichiers __init__.py ne sont plus nécessaires.

110
Igonato

Je l'ai compris. Très frustrant, surtout venant de python2.

Vous devez ajouter un . au module, qu'il soit relatif ou absolu.

J'ai créé la configuration du répertoire comme suit.

/main.py
--/lib
  --/__init__.py
  --/mody.py
  --/modx.py

modx.py

def does_something():
    return "I gave you this string."

mody.py

from modx import does_something

def loaded():
    string = does_something()
    print(string)

main.py

from lib import mody

mody.loaded()

quand j'exécute main, c'est ce qui se passe

$ python main.py
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    from lib import mody
  File "/mnt/c/Users/Austin/Dropbox/Source/Python/virtualenviron/mock/package/lib/mody.py", line 1, in <module>
    from modx import does_something
ImportError: No module named 'modx'

J'ai couru 2to3, et la sortie principale était-ce

RefactoringTool: Refactored lib/mody.py
--- lib/mody.py (original)
+++ lib/mody.py (refactored)
@@ -1,4 +1,4 @@
-from modx import does_something
+from .modx import does_something

 def loaded():
     string = does_something()
RefactoringTool: Files that need to be modified:
RefactoringTool: lib/modx.py
RefactoringTool: lib/mody.py

Je devais modifier la déclaration d'importation de mody.py pour y remédier

try:
    from modx import does_something
except ImportError:
    from .modx import does_something


def loaded():
    string = does_something()
    print(string)

Ensuite, j'ai de nouveau exécuté main.py et obtenu le résultat attendu

$ python main.py
I gave you this string.

Enfin, juste pour le nettoyer et le rendre portable entre 2 et 3.

from __future__ import absolute_import
from .modx import does_something
41
user3159377

La définition de PYTHONPATH peut également aider à résoudre ce problème.

Voici comment cela peut être fait sous Windows

set PYTHONPATH=.

21
Santosh Pillai

Essayé votre exemple

from . import config

a obtenu l'erreur SystemError suivante:
/usr/bin/python3.4 test.py
Traceback (dernier appel passé):
Fichier "test.py", ligne 1, dans
de . importation config
SystemError: le module parent '' n'est pas chargé, impossible d'effectuer l'importation relative


Cela fonctionnera pour moi:

import config
print('debug=%s'%config.debug)

>>>debug=True

Testé avec Python: 3.4.2 - PyCharm 2016.3.2


A côté de cela, PyCharm vous propose d'importer ce nom .
Vous devez cliquer sur config et une icône d’aide apparaît. enter image description here

10
stovfl

Vous pouvez simplement ajouter le fichier suivant à votre répertoire de tests, puis python l'exécutera avant les tests

__init__.py file

import os
import sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
6
Vinod Rane

Vous devez ajouter le chemin du module à PYTHONPATH:

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"
5
Giorgos Myrianthous

Cet exemple fonctionne sur Python 3.6.

Je suggère d’aller dans Run -> Edit Configurations dans PyCharm, d’y supprimer toutes les entrées et d’essayer de réexécuter le code dans PyCharm.

Si cela ne fonctionne pas, vérifiez votre interpréteur de projet (Paramètres -> Interprète de projet) et exécutez les paramètres de configuration par défaut (Exécuter -> Modifier les configurations ...).

3
Carson Crane

Déclarez la bonne sys.path liste avant d'appeler le module:

import os, sys

#'/home/user/example/parent/child'
current_path = os.path.abspath('.')

#'/home/user/example/parent'
parent_path = os.path.dirname(current_path)

sys.path.append(parent_path)
os.environ.setdefault('Django_SETTINGS_MODULE', 'child.settings')
1
HoangYell