La importación del paquete instalado desde el script genera “AttributeError: el módulo no tiene ningún atributo” o “ImportError: no se puede importar el nombre”

Tengo un script llamado requests.py que importa el paquete de solicitudes. La secuencia de comandos no puede acceder a los atributos del paquete o no puede importarlos. ¿Por qué no funciona esto y cómo lo arreglo?

El siguiente código genera 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  import requests File "/Users/me/dev/rough/requests.py", line 3, in  requests.get('http://www.google.ca') AttributeError: module 'requests' has no attribute 'get' 

El siguiente código genera 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  from requests import get File "/Users/me/dev/rough/requests.py", line 1, in  from requests import get ImportError: cannot import name 'get' 

O código que importa desde un módulo dentro del paquete de requests :

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

Esto sucede porque su módulo local llamado requests.py oculta el módulo de requests instalado que está tratando de usar. El directorio actual se sys.path a sys.path , por lo que el nombre local tiene prioridad sobre el nombre instalado.

Una sugerencia de depuración adicional cuando aparezca es mirar cuidadosamente el Traceback y darse cuenta de que el nombre de su script en cuestión coincide con el módulo que intenta importar:

Note el nombre que usó en su script:

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

El módulo que está intentando importar: requests

Cambie el nombre de su módulo a otra cosa para evitar la colisión de nombres.

Python puede generar un archivo requests.pyc junto a su archivo requests.py (en el directorio __pycache__ en Python 3). Elimínelo también después de su cambio de nombre, ya que el intérprete seguirá haciendo referencia a ese archivo y volverá a producir el error. Sin embargo, el archivo pyc en __pycache__ no debería afectar su código si el archivo py ha sido eliminado.

En el ejemplo, cambiar el nombre del archivo a my_requests.py , eliminar requests.pyc y ejecutar de nuevo correctamente imprime .

Para el autor de la pregunta original, y para aquellas personas que buscan en la cadena “AttributeError: module no tiene ningún atributo”, la explicación común según la respuesta aceptada es que un script creado por el usuario tiene un conflicto de nombres con una biblioteca. nombre del archivo. Sin embargo, tenga en cuenta que el problema podría no estar en el nombre de la secuencia de comandos que genera el error (como ocurrió en el caso anterior), ni en ninguno de los nombres de los módulos de la biblioteca importados explícitamente por esa secuencia de comandos. Puede tomar un poco de trabajo de detective para averiguar qué archivo está causando el problema.

Como ejemplo para ilustrar el problema, imagine que está creando una secuencia de comandos que utiliza la biblioteca “decimal” para cálculos precisos de punto flotante con números decimales, y denomina a su secuencia de comandos ” mydecimal.py ” que contiene la línea ” import decimal ” . No hay problema con nada de eso, pero encuentras que genera este error:

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

Esto sucedería si anteriormente hubiera escrito un script llamado ” numbers.py ” porque la biblioteca “decimal” llama a los “números” de la biblioteca estándar pero encuentra su antiguo script en su lugar. Incluso si lo hubieras eliminado, podría no terminar el problema porque Python podría haberlo convertido en código de bytes y haberlo almacenado en un caché como ” numbers.pyc “, por lo que también deberías buscarlo.