externally-managed-environment en pip: cómo solucionarlo

Publicado:

16 min de lectura

Acar Diveroli
Autor: Acar Diveroli
pip install requests con cursor azul, comprobación rechazada en EXTERNALLY-MANAGED, error rojo y la solución python3 -m venv.

Configuras un servidor nuevo con Ubuntu 24.04, una Raspberry Pi o un Mac con Homebrew, escribes pip install requests como llevas años haciendo, y pip se detiene con error: externally-managed-environment. El mismo comando sigue funcionando en tu equipo antiguo, y el mensaje te pide que uses apt, un entorno virtual o pipx en su lugar.

Esta guía explica qué protege el error, qué sistemas lo activan y las soluciones en el orden en que las recomendamos, con la opción que desactiva la comprobación al final. Ejecutamos cada comando contra una reproducción del error. Las últimas secciones tratan pip detrás de un servidor proxy y una primera petición a través de un proxy desde el nuevo entorno.

¿Qué significa «error: externally-managed-environment»?

Significa que pip encontró un marcador que indica que otra herramienta es dueña de esta instalación de Python. PEP 668 define el marcador: un archivo llamado EXTERNALLY-MANAGED en el directorio de la biblioteca estándar del intérprete, por ejemplo /usr/lib/python3.13/ en Debian 13. pip lee el archivo desde la versión 23.0, publicada en enero de 2023. Cuando el archivo existe y pip no se ejecuta dentro de un entorno virtual, pip imprime el texto del archivo y termina sin instalar nada.

Reprodujimos el error en Windows 11 con pip 26.2.1: colocamos el texto del marcador de Debian 13 en el directorio de la biblioteca estándar de un Python 3.14.8 desechable y ejecutamos python -m pip install requests. La salida coincide con lo que ven los usuarios de Debian:

text
error: externally-managed-environment

× This environment is externally managed
╰─> To install Python packages system-wide, try apt install
    python3-xyz, where xyz is the package you are trying to
    install.

    If you wish to install a non-Debian-packaged Python package,
    create a virtual environment using python3 -m venv path/to/venv.
    Then use path/to/venv/bin/python and path/to/venv/bin/pip. Make
    sure you have python3-full installed.

    If you wish to install a non-Debian packaged Python application,
    it may be easiest to use pipx install xyz, which will manage a
    virtual environment for you. Make sure you have pipx installed.

    See /usr/share/doc/python3.13/README.venv for more information.

note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.
hint: See PEP 668 for the detailed specification.

Las dos primeras líneas, la note y el hint vienen de pip. El bloque con sangría es el texto del archivo marcador, así que cambia según el sistema: Arch Linux sugiere pacman -S python-xyz, Homebrew sugiere brew install xyz, y ambos remiten también a un entorno virtual y a pipx.

¿Por qué pip se niega a instalar aquí?

Porque, si no, dos gestores de paquetes escribirían en el mismo directorio sin saber el uno del otro. En Debian, Ubuntu o Arch, partes del sistema operativo están escritas en Python e importan bibliotecas que instaló el gestor de paquetes del sistema. Ese gestor registra qué versiones necesitan esos programas; pip no lee esos registros. PEP 668 describe el resultado: un pip install puede actualizar o eliminar una biblioteca que trae el sistema operativo e incluso romper el propio gestor de paquetes de Fedora, dnf.

Mandar pip a un directorio aparte tampoco lo resuelve. Las distribuciones colocan los paquetes instalados localmente en lugares como /usr/local, y en la disposición que recomienda PEP 668 las instalaciones locales tienen prioridad sobre los paquetes de la distribución, así que los programas de Python del sistema importan lo que pip haya dejado ahí. El marcador zanja la cuestión: los proyectos tienen sus propios entornos y el Python del sistema se queda tal como lo construyó la distribución.

¿Cómo decide pip si bloquea una instalación?

  1. Comprueba si está en un entorno virtual. Dentro de un venv, sys.prefix es distinto de sys.base_prefix, la comprobación termina y la instalación sigue adelante.
  2. Busca el marcador en el directorio que devuelve sysconfig.get_path("stdlib").
  3. Lee el mensaje de la clave Error del archivo, o de una clave traducida Error-<idioma> si el archivo la tiene, y lo imprime.
  4. Bloquea tanto pip install como pip uninstall. --user no ayuda: pip install --user requests se detuvo con el mismo error en nuestra prueba. Ejecutar pip con sudo no cambia nada.
  5. La opción --break-system-packages se salta la comprobación, y lo mismo hacen sus formas como variable de entorno y en el archivo de configuración, que veremos más abajo.

Para saber en qué caso estás, pregunta al intérprete que vas a usar:

bash
python3 -c "import os, sys, sysconfig; print('venv:', sys.prefix != sys.base_prefix); print('marker:', os.path.isfile(os.path.join(sysconfig.get_path('stdlib'), 'EXTERNALLY-MANAGED')))"

pip bloquea la instalación solo cuando esto imprime venv: False y marker: True. Dentro de un entorno virtual, el marcador del intérprete base sigue visible, así que nuestro venv también imprimió marker: True, pero la primera línea decía venv: True y pip instaló con normalidad.

¿Qué sistemas incluyen el marcador?

Debian, Ubuntu, Raspberry Pi OS, Arch Linux y Homebrew lo incluyen; Fedora y las imágenes oficiales de Docker, no.

SistemaMarcadorEl mensaje sugiere
Debian 12 y posterioresSíapt install python3-xyz, venv, pipx
Ubuntu 23.04 y posterioresSíEl mismo texto que Debian
Raspberry Pi OS Bookworm y posterioresSíEl mismo texto que Debian
Arch LinuxSípacman -S python-xyz, venv, pipx
Python de HomebrewSíbrew install xyz, venv, pipx
FedoraNopip instala en /usr/local
Imágenes oficiales de Docker pythonNoNo aplica

Debian marcó su paquete de Python 3.11 antes de publicar Debian 12, y Ubuntu 23.04 incluyó ese mismo paquete, así que Ubuntu 24.04 LTS y los sistemas Ubuntu o Debian que mucha gente usa en WSL en Windows muestran el mismo mensaje. Fedora toma otro camino: no incluye ningún marcador y envía sudo pip install a /usr/local.

Solución 1: crea un entorno virtual para tu proyecto

Un entorno virtual (venv) es un directorio con su propio python y su propia carpeta de paquetes, vinculado al intérprete del sistema pero separado de sus paquetes. Dentro de él, pip se salta la comprobación de PEP 668, y nada de lo que instales ahí puede tocar el sistema.

bash
cd ~/my-project
python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests

En nuestra prueba, el último comando terminó con:

text
Successfully installed certifi-2026.7.22 charset_normalizer-3.5.2 idna-3.20 requests-2.34.2 urllib3-2.8.0

Activar el entorno solo pone su directorio bin al principio de tu PATH. La documentación de venv de Python indica el comando para cada shell, con .venv\Scripts\activate en Windows. Puedes saltarte la activación y llamar directamente al intérprete del entorno, que es la forma más segura en scripts, tareas cron y unidades de systemd:

bash
.venv/bin/python -m pip install requests
.venv/bin/python app.py

Trata .venv como algo desechable. Déjalo fuera de Git (desde Python 3.13, venv escribe un .gitignore dentro de la carpeta), registra tus paquetes con python -m pip freeze > requirements.txt y reconstruye el entorno en otro sitio con python -m pip install -r requirements.txt. Un venv no sobrevive a que lo muevas o lo copies a otro equipo; créalo de nuevo allí.

En VS Code, la extensión de Python encuentra una carpeta .venv en el espacio de trabajo y la prefiere. Si elige otro intérprete, ejecuta Python: Select Interpreter (Python: seleccionar intérprete) desde la paleta de comandos (Command Palette; Ctrl+Shift+P, o Cmd+Shift+P en Mac) y elige el que está dentro de .venv; a partir de ahí, las terminales nuevas se abren con el entorno activo.

«ensurepip is not available» en Debian y Ubuntu

Debian distribuye el soporte de venv en un paquete aparte, así que en un servidor mínimo el propio comando python3 -m venv .venv puede fallar. El módulo venv parcheado por Debian imprime este mensaje, con el número de versión de tu Python:

text
The virtual environment was not created successfully because ensurepip is not
available.  On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.

    apt install python3.13-venv

Instala el paquete (python3-venv arrastra el de tu versión concreta), borra la carpeta creada a medias y vuelve a ejecutar el comando:

bash
sudo apt install python3-venv
rm -rf .venv
python3 -m venv .venv

Solución 2: instala herramientas de línea de comandos con pipx

Si quieres un programa y no una biblioteca, como un formateador, un linter o un cliente HTTP, usa pipx, la herramienta que sugiere el propio mensaje de error. pipx crea un entorno virtual por aplicación y pone sus comandos en tu PATH, así que las herramientas nunca rompen las dependencias de las demás.

bash
sudo apt install pipx      # macOS: brew install pipx
pipx ensurepath
pipx install ruff

Abre una terminal nueva después de pipx ensurepath. En nuestra prueba, pipx install ruff informó installed package ruff 0.17.0 y el comando ruff funcionó al instante; más adelante lo gestionas con pipx upgrade ruff y pipx uninstall ruff. La guía de instalación de pipx tiene los comandos para otros sistemas.

Solución 3: usa el paquete de la propia distribución

Si una biblioteca la necesita un script del sistema, puede que la distribución ya la empaquete. Debian, Ubuntu y Raspberry Pi OS nombran las bibliotecas de Python python3-<nombre>; Arch usa python-<nombre>:

bash
sudo apt install python3-requests     # Debian, Ubuntu, Raspberry Pi OS
sudo pacman -S python-requests        # Arch Linux

Estas versiones reciben las actualizaciones de seguridad de la distribución, pero a menudo son más antiguas que la última versión publicada en PyPI. Homebrew empaqueta aplicaciones, y su documentación te remite a un venv para las bibliotecas.

A veces un proyecto necesita ambas cosas: una biblioteca de hardware de apt en una Raspberry Pi y un paquete más reciente de PyPI. Crea el entorno con python3 -m venv --system-site-packages .venv. El venv ve entonces los paquetes del sistema, y pip sigue instalando solo en el venv. En nuestra prueba, requests fue a .venv mientras una biblioteca del sistema ya instalada se cargaba desde la carpeta del sistema.

Solución 4: usa uv para entornos y herramientas

uv es un gestor de paquetes y proyectos que sustituye varios comandos de pip, venv y pipx por un solo programa. También respeta el marcador: uv pip install --system contra nuestro Python marcado se detuvo con error: The interpreter at … is externally managed, seguido del mismo texto de Debian. Su flujo normal usa un entorno virtual, así que el error no aparece:

bash
uv venv
uv pip install requests
uv tool install ruff

uv venv crea .venv en la carpeta actual, uv pip install instala en él sin activarlo y uv tool install es el equivalente de pipx install. Los tres funcionaron en nuestra prueba.

Contenedores y pipelines de CI

Las imágenes oficiales de python en Docker Hub compilan su propio Python en /usr/local y no incluyen marcador, así que pip install funciona en ellas como antes. El error aparece cuando un Dockerfile parte de una imagen debian o ubuntu e instala Python con apt. La solución es la misma que en el portátil: instala python3-venv, crea el entorno con RUN python3 -m venv /opt/venv y añade ENV PATH="/opt/venv/bin:$PATH". Todos los RUN pip install -r requirements.txt posteriores y el python del contenedor usan entonces el venv, igual que tras una activación.

Los sistemas de CI suelen abrir una shell nueva en cada paso, así que una activación anterior se pierde. Llama al intérprete del entorno por su ruta (.venv/bin/python -m pip install …, .venv/bin/python -m pytest) en cada paso.

¿Por qué --break-system-packages es el último recurso?

Desactiva la protección en lugar de resolver el conflicto, y funciona: en nuestra reproducción, pip install --break-system-packages requests instaló el paquete en el Python marcado, y lo mismo hicieron la variable de entorno PIP_BREAK_SYSTEM_PACKAGES=1 y la línea break-system-packages = true en la sección [global] de un archivo de configuración de pip. La opción no hace segura la instalación; solo quita el aviso, y pip puede ahora actualizar o eliminar una biblioteca que importan las propias herramientas del sistema. Una actualización posterior del sistema puede entonces sobrescribir lo que instaló pip.

Borrar el archivo EXTERNALLY-MANAGED tiene el mismo efecto para todos los usuarios y programas del equipo. Si de verdad necesitas saltarte la comprobación, hazlo donde el daño quede contenido, como un contenedor que reconstruyes o una máquina virtual, y nunca en un perfil de shell ni en una configuración global de pip, donde se aplica en silencio a cada instalación posterior.

¿Cómo usas pip detrás de un servidor proxy?

Pasa a pip la URL del proxy con --proxy, con la variable HTTPS_PROXY o en su archivo de configuración. Las redes de empresas y universidades a menudo solo permiten el tráfico web a través de un servidor proxy que pide usuario y contraseña, y pip no presenta la falta de credenciales como un problema del proxy. Sin credenciales, nuestro proxy de prueba local respondió a cada intento con el estado 407, y pip imprimió cinco reintentos (abajo quitamos cuatro) y una conclusión engañosa:

text
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'OSError('Tunnel connection failed: 407 Proxy Authentication Required')': /simple/requests/
ERROR: Could not find a version that satisfies the requirement requests (from versions: none)
ERROR: No matching distribution found for requests

from versions: none significa que pip nunca llegó al índice de paquetes, no que el paquete no exista. La guía de usuario de pip enumera todas las opciones; estas tres cubren la mayoría de los casos:

bash
# para un solo comando
python -m pip install --proxy http://user:pass@proxy.example.com:8080 requests

# para todos los comandos de esta shell
export HTTPS_PROXY=http://user:pass@proxy.example.com:8080

# guardado solo en el entorno virtual activo
python -m pip config --site set global.proxy http://user:pass@proxy.example.com:8080

Las tres instalaron requests a través de nuestro proxy de prueba. Con --site, pip escribió el ajuste en el archivo de configuración propio del venv (pip.conf, o pip.ini en Windows); sin esa opción, pip config set escribe en tu archivo de usuario, que se aplica a todos los entornos. Si la contraseña contiene @, : o /, codifica esos caracteres con codificación porcentual (percent-encoding); Cómo solucionar HTTP 407 Proxy Authentication Required explica la codificación y otros errores de credenciales.

Detrás de un proxy que inspecciona el tráfico HTTPS, el siguiente error suele ser CERTIFICATE_VERIFY_FAILED. Desde la versión 24.2, pip también confía en los certificados del sistema operativo, así que un certificado raíz de la empresa que el equipo de TI instaló en el almacén del sistema a menudo lo soluciona, y --cert indica a pip un archivo de bundle. Unable to Get Local Issuer Certificate: cómo solucionarlo explica cómo distinguir las causas.

¿Cómo envías una primera petición a través de un proxy desde el venv?

Con requests instalado en el venv, una petición a través de un proxy solo necesita un diccionario. El script lee la URL del proxy de una variable de entorno, así que las credenciales quedan fuera del código:

python
import os
import sys

import requests

# El endpoint y las credenciales de tu panel de proxy
PROXY = os.environ.get("PROXY_URL", "http://user:pass@pr.proxynet.io:8000")
proxies = {"http": PROXY, "https": PROXY}

print("Python:", sys.executable)
try:
    r = requests.get("https://example.com/", proxies=proxies, timeout=15)
    print("Status:", r.status_code)
except requests.exceptions.ProxyError as err:
    print("Proxy error:", err)

Ejecútalo con .venv/bin/python first_request.py. A través de nuestro proxy de prueba local, la línea Python: mostró el intérprete de .venv y la segunda línea decía Status: 200. Con una contraseña incorrecta, imprimió un Proxy error que terminaba en Tunnel connection failed: 407 Proxy Authentication Required. Lanzado con el python3 del sistema, el script ni siquiera llegó tan lejos: ModuleNotFoundError: No module named 'requests', porque los paquetes están en el venv.

El tipo de proxy decide cómo ven tus peticiones los sitios de destino. Los Proxies residenciales salen por conexiones domésticas del país y la ciudad que elijas, con una dirección nueva en cada petición o una sesión fija de 1 a 60 minutos; úsalos para ver las páginas como las ven los visitantes locales, respetando las condiciones y los límites de solicitudes de cada sitio.

Los Proxies de centro de datos te dan direcciones IPv4 dedicadas con tráfico sin cuota, algo que encaja con tareas constantes como comprobar tus propios servicios y APIs desde varios países. Para enviar datos en lugar de obtenerlos, POST con JSON en Python Requests: equivalencias de cURL explica json=, las cabeceras y los comandos cURL equivalentes.

Dónde te encuentras este error

  • Servidores nuevos e imágenes de VPS con Debian 12 o posterior o con Ubuntu 24.04, donde los scripts de instalación antiguos todavía llaman a sudo pip install.
  • Proyectos con Raspberry Pi que siguen tutoriales antiguos para bibliotecas de sensores y GPIO.
  • Macs en los que python3 viene de Homebrew.
  • Dockerfiles basados en imágenes debian o ubuntu que instalan Python con apt.
  • WSL en Windows, que ejecuta Ubuntu o Debian.
  • Trabajos de CI después de que la imagen base pase a una versión más nueva.

Errores comunes

  • Ejecutar sudo pip install dentro de un venv activado. En Debian, sudo sustituye PATH por una lista fija (secure_path), encuentra el pip del sistema y el error vuelve. Un venv en tu carpeta personal no necesita sudo.
  • Instalar en el venv pero ejecutar con python3. El intérprete del sistema no ve los paquetes del venv y falla con ModuleNotFoundError.
  • Subir .venv a Git o copiarlo a otro equipo. Reconstrúyelo a partir de requirements.txt.
  • Poner break-system-packages en una configuración global de pip. Desactiva la protección para cada instalación posterior.

Guía de decisión

Tu objetivoUsa
Bibliotecas para un proyectopython3 -m venv .venv
Una herramienta de línea de comandospipx install <herramienta>
Una biblioteca para un script del sistemaapt install python3-<nombre>
Paquetes del sistema más paquetes de PyPIvenv --system-site-packages
Una sola herramienta para entornos y herramientasuv venv, uv tool install
Imagen de Docker sobre Debian o Ubuntuvenv en /opt/venv, primero en PATH
pip detrás de un proxy de empresa--proxy o HTTPS_PROXY
Un contenedor que vas a desechar--break-system-packages

Preguntas frecuentes

¿Por qué pip install dejó de funcionar después de actualizar Ubuntu o Debian?

Tu nueva versión incluye el marcador EXTERNALLY-MANAGED, y pip 23.0 y posteriores lo respetan. Debian 12 y Ubuntu 23.04 fueron las primeras versiones con el archivo, así que pasar de Debian 11 o Ubuntu 22.04 es el desencadenante habitual.

¿Es seguro usar --break-system-packages?

No en un sistema que quieras conservar. Permite que pip reemplace o elimine bibliotecas que importan las propias herramientas de Python del sistema operativo. Úsalo solo en un contenedor o una máquina virtual que puedas reconstruir.

¿pip install --user evita el error?

No. La comprobación mira el intérprete, no la carpeta de usuario a la que irían los archivos, así que las instalaciones con --user también se bloquean; nuestra prueba lo confirmó.

¿Puedo borrar el archivo EXTERNALLY-MANAGED?

Puedes, pero desactiva la protección para todos los usuarios y programas del equipo, exactamente igual que un --break-system-packages global, y una actualización posterior del paquete de Python puede restaurar el archivo. Un venv resuelve el problema sin ninguno de esos dos efectos secundarios.

¿Tengo que activar el entorno virtual cada vez?

No. La activación cambia PATH solo en la shell actual. Llamar a .venv/bin/python (.venv\Scripts\python.exe en Windows) usa el entorno directamente, y es la forma fiable para scripts, servicios y CI.

¿Por qué pip sigue mostrando el error dentro de mi entorno virtual?

Porque el pip que ejecutaste no es el del venv: sudo, una terminal nueva sin activación o la terminal de un editor que usa el intérprete del sistema. Ejecuta python -m pip --version; la ruta que imprime debería apuntar dentro de .venv.

En resumen

error: externally-managed-environment es el sistema operativo diciéndole a pip que no le corresponde cambiar el Python del sistema. Da a cada proyecto un entorno virtual, da a cada herramienta de línea de comandos el suyo mediante pipx y deja el Python del sistema en manos de apt, pacman o Homebrew. Reserva --break-system-packages para máquinas que puedas desechar. Cuando esos scripts necesiten llegar a sitios desde otras ubicaciones, consulta nuestra página de servicios de proxy.