web-dev-qa-db-fra.com

L'importation du package installé à partir du script déclenche "AttributeError: le module n'a pas d'attribut" ou "ImportError: impossible d'importer le nom"

J'ai un script nommé requests.py qui importe le package de demandes. Le script ne peut pas accéder aux attributs du package ou ne peut pas les importer. Pourquoi cela ne fonctionne-t-il pas et comment le corriger?

Le code suivant déclenche un AttributeError.

import requests

res = requests.get('http://www.google.ca')
print(res)
Traceback (most recent call last):
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    import requests
  File "/Users/me/dev/rough/requests.py", line 3, in <module>
    requests.get('http://www.google.ca')
AttributeError: module 'requests' has no attribute 'get'

Le code suivant déclenche un ImportError.

from requests import get

res = get('http://www.google.ca')
print(res)
Traceback (most recent call last):
  File "requests.py", line 1, in <module>
    from requests import get
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests import get
ImportError: cannot import name 'get'

Ou du code qui importe à partir d'un module à l'intérieur du package requests:

from requests.auth import AuthBase
Traceback (most recent call last):
  File "requests.py", line 1, in <module>
    from requests.auth import AuthBase
  File "/Users/me/dev/rough/requests.py", line 1, in <module>
    from requests.auth import AuthBase
ImportError: No module named 'requests.auth'; 'requests' is not a package
42
idjaw

Cela se produit car votre module local nommé requests.py masque le module requests installé que vous essayez d'utiliser. Le répertoire actuel est ajouté à sys.path, le nom local est donc prioritaire sur le nom installé.

Une astuce de débogage supplémentaire lorsque cela se produit consiste à examiner attentivement le Traceback et à réaliser que le nom de votre script en question correspond au module que vous essayez d'importer:

Notez le nom que vous avez utilisé dans votre script:

File "/Users/me/dev/rough/requests.py", line 1, in <module>

Le module que vous essayez d'importer: requests

Renommez votre module en quelque chose d'autre pour éviter la collision de noms.

Python peut générer un requests.pyc fichier à côté de votre requests.py fichier (dans le __pycache__ répertoire dans Python 3). Supprimez-le également après votre renommage, car l'interpréteur fera toujours référence à ce fichier, reproduisant l'erreur. Cependant, le fichier pyc dans __pycache__devrait n'affecte pas votre code si le fichier py a été supprimé.

Dans l'exemple, renommer le fichier en my_requests.py, suppression requests.pyc, et une nouvelle exécution réussit à imprimer <Response [200]>.

50
idjaw

Pour l'auteur de la question d'origine et pour les personnes recherchant la chaîne "AttributeError: module has no attribute", alors l'explication courante selon la réponse acceptée est qu'un script créé par l'utilisateur a un conflit de noms avec une bibliothèque nom de fichier. Notez cependant que le problème peut ne pas provenir du nom du script qui génère l'erreur (comme c'était le cas dans le cas ci-dessus), ni des noms des modules de bibliothèque importés explicitement par ce script. Cela peut prendre un peu de travail de détective pour déterminer quel fichier est à l'origine du problème.

À titre d'exemple pour illustrer le problème, imaginez que vous créez un script qui utilise la bibliothèque "décimale" pour des calculs précis en virgule flottante avec des nombres décimaux, et que vous nommez votre script "mydecimal.py "qui contient la ligne" import decimal ". Il n'y a aucun problème avec cela, mais vous constatez qu'il déclenche cette erreur:

AttributeError: 'module' object has no attribute 'Number'

Cela se produirait si vous aviez précédemment écrit un script appelé "numbers.py "car la bibliothèque" décimale "appelle les" numéros "standard de la bibliothèque mais trouve votre ancien script à la place. Même si vous l'aviez supprimé, cela ne pourrait pas mettre fin au problème car python pourrait avoir converti cela en bytecode et stocké dans un cache en tant que "numbers.pyc ", vous devrez donc également le rechercher.

9
Dave Rove