¿Alguna vez has pensado en cómo funcionan las bibliotecas de entorno virtual en Python? En este artículo, sugiero familiarizarse con el concepto principal que utilizan todas las bibliotecas para entornos, como virtualenv, virtualenvwrapper, conda, pipenv.
Inicialmente, en Python no había una capacidad incorporada para crear entornos, y esta característica se implementó como un truco. Al final resultó que, todas las bibliotecas se basan en una característica muy simple del intérprete de Python.
Cuando Python inicia el intérprete, comienza a buscar el directorio con los módulos (paquetes de sitio). La búsqueda comienza con el directorio principal con respecto a la ubicación física del ejecutable del intérprete (python.exe). Si no se encuentra la carpeta del módulo, Python sube un nivel más y lo hace hasta que se alcanza el directorio raíz. Para comprender que este es un directorio con módulos, Python busca el módulo os, que debe estar en el archivo os.py y es necesario para que Python funcione.
Imaginemos que nuestro intérprete se encuentra en
/usr/dev/lang/bin/python
. Entonces las rutas de búsqueda se verán así:
/usr/dev/lang/lib/python3.7/os.py /usr/dev/lib/python3.7/os.py /usr/lib/python3.7/os.py /lib/python3.7/os.py
Como puede ver, Python agrega un prefijo especial (
lib/python$VERSION/os.py
) a nuestra ruta. Tan pronto como el intérprete encuentra la primera coincidencia (la presencia del archivo os.py), cambia
sys.prefix
y
sys.exec_prefix
a esta ruta (sin el prefijo). Si por alguna razón no se encuentran coincidencias, se utiliza la ruta estándar, que se compila en el intérprete.
Ahora veamos cómo lo hace una de las bibliotecas más antiguas y famosas, virtualenv.
user@arb:/usr/home/test
Después de la ejecución, crea directorios adicionales:
user@arb:/usr/home/test/ENV
Como puede ver, el entorno virtual se creó copiando el binario de Python a una carpeta local (ENV / bin / python). También podemos notar que la carpeta principal contiene
enlaces simbólicos a los archivos de la biblioteca estándar de Python. No podemos crear un enlace simbólico al archivo ejecutable, como el intérprete lo cambiará de nombre a la ruta real.
Ahora activemos nuestro entorno:
user@arb:/usr/home/test
Este comando cambia la variable de entorno $ PATH para que el comando
python
apunte a nuestra versión local de python. Esto se logra al sustituir la ruta local de la carpeta bin al comienzo de la línea $ PATH para que la ruta local tenga prioridad sobre todas las rutas a la derecha.
export "/usr/home/test/ENV/bin:$PATH" echo $PATH
Si ejecuta el script desde este entorno, se ejecutará utilizando el binario en
/usr/home/test/ENV/bin/python
. El intérprete utilizará esta ruta como punto de partida para encontrar módulos. En nuestro caso, los módulos de la biblioteca estándar se encontrarán en la ruta
/usr/home/test/ENV/lib/python3.7/
.
Este es el truco principal, gracias al cual funcionan todas las bibliotecas para trabajar con entornos virtuales.
Mejoras en Python 3
A partir de la versión Python 3.3, apareció un nuevo estándar, denominado
PEP 405 , que introduce un nuevo mecanismo para entornos livianos.
Este PEP agrega un paso adicional al proceso de búsqueda. Si crea el
pyenv.cfg
configuración
pyenv.cfg
, en lugar de copiar el binario de Python y todos sus módulos, simplemente puede indicar su ubicación en esta configuración.
Esta característica es utilizada activamente por el módulo
venv estándar, que apareció en Python 3.
user@arb:/usr/home/test2
user@arb:/usr/home/test2
Gracias a esta configuración, en lugar de copiar el binario, venv simplemente crea un enlace a él. Si el parámetro
include-system-site-packages
cambia a
true
, todos los módulos de la biblioteca estándar serán accesibles automáticamente desde el entorno virtual.
A pesar de estos cambios, la mayoría de las bibliotecas de terceros para trabajar con entornos virtuales utilizan el enfoque anterior.
PD: Soy el autor de este artículo, puedes hacer cualquier pregunta.