site — Configuración de todo el sitio

El módulo site maneja la configuración específica del sitio, especialmente la ruta de importación.

Ruta de importación

site se importa automáticamente cada vez que se inicia el intérprete. En la importación, extiende sys.path con nombres específicos del sitio construidos combinando los valores de prefijo sys.prefix y sys.exec_prefix con varios sufijos. Los valores de prefijo utilizados se guardan en la variable de nivel de módulo PREFIXES para su posterior consulta. En Windows, los sufijos son una cadena vacía y lib/site-packages. Para plataformas tipo Unix, los valores son lib/python$version/site-packages (donde $version se reemplaza por el número de versión mayor y menor del intérprete, como 3.5 ) y lib/site-python.

site_import_path.py
import sys
import os
import site

if 'Windows' in sys.platform:
    SUFFIXES = [
        '',
        'lib/site-packages',
    ]
else:
    SUFFIXES = [
        'lib/python{}/site-packages'.format(sys.version[:3]),
        'lib/site-python',
    ]

print('Path prefixes:')
for p in site.PREFIXES:
    print('  ', p)

for prefix in sorted(set(site.PREFIXES)):
    print()
    print(prefix)
    for suffix in SUFFIXES:
        print()
        print(' ', suffix)
        path = os.path.join(prefix, suffix).rstrip(os.sep)
        print('   exists :', os.path.exists(path))
        print('   in path:', path in sys.path)

Cada una de las rutas resultantes de las combinaciones se prueba, y las que existen se agregan a sys.path. Este resultado muestra la versión de marco de Python instalada en un sistema Mac OS X.

$ python3 site_import_path.py

Path prefixes:
   /Library/Frameworks/Python.framework/Versions/3.5
   /Library/Frameworks/Python.framework/Versions/3.5

/Library/Frameworks/Python.framework/Versions/3.5

  lib/python3.5/site-packages
   exists : True
   in path: True

  lib/site-python
   exists : False
   in path: False

Directorios de usuarios

Además de las rutas globales de paquetes de sitio, site es responsable de agregar las ubicaciones específicas del usuario a la ruta de importación. Las rutas específicas del usuario se basan en el directorio USER_BASE, que generalmente se encuentra en una parte del sistema de archivos que posee (y puede escribir) el usuario actual. Dentro del directorio USER_BASE hay un directorio site-packages, con la ruta accesible como USER_SITE.

site_user_base.py
import site

print('Base:', site.USER_BASE)
print('Site:', site.USER_SITE)

La ruta USER_SITE se crea utilizando los mismos valores de sufijo específicos de la plataforma descritos anteriormente.

$ python3 site_user_base.py

Base: /Users/dhellmann/.local
Site: /Users/dhellmann/.local/lib/python3.6/site-packages

El directorio base del usuario se puede establecer a través de la variable de entorno PYTHONUSERBASE, y tiene valores predeterminados específicos de la plataforma (~/Python$version/site-packages para Windows y ~/.local para no Windows).

$ PYTHONUSERBASE=/tmp/$USER python3 site_user_base.py

Base: /tmp/dhellmann
Site: /tmp/dhellmann/lib/python3.6/site-packages

El directorio de usuarios está deshabilitado en algunas circunstancias que plantearían problemas de seguridad (por ejemplo, si el proceso se ejecuta con una identificación efectiva de usuario o grupo diferente al usuario real que lo inició). Una aplicación puede verificar la configuración examinando ENABLE_USER_SITE.

site_enable_user_site.py
import site

status = {
    None: 'Disabled for security',
    True: 'Enabled',
    False: 'Disabled by command-line option',
}

print('Flag   :', site.ENABLE_USER_SITE)
print('Meaning:', status[site.ENABLE_USER_SITE])

El directorio del usuario también se puede deshabilitar explícitamente en la línea de comando con -s.

$ python3 site_enable_user_site.py

Flag   : True
Meaning: Enabled

$ python3 -s site_enable_user_site.py

Flag   : False
Meaning: Disabled by command-line option

Archivos de configuración de ruta

A medida que se agregan rutas a la ruta de importación, también se analizan en busca de archivos de configuración de ruta. Un archivo de configuración de ruta es un archivo de texto sin formato con la extensión .pth. Cada línea en el archivo puede tomar una de cuatro formas.

  • Una ruta completa o relativa a otra ubicación que debe agregarse a la ruta de importación.
  • Una declaración de Python para ser ejecutada. Todas estas líneas deben comenzar con una declaración import.
  • Las líneas en blanco se ignoran.
  • Una línea que comienza con # se trata como un comentario y se ignora.

Los archivos de configuración de ruta se pueden usar para extender la ruta de importación para buscar en ubicaciones que no se habrían agregado automáticamente. Por ejemplo, el paquete setuptools agrega una ruta a easy-install.pth cuando instala un paquete en modo de desarrollo usando python setup.py development.

La función para extender sys.path es pública y se puede usar en programas de ejemplo para mostrar cómo funcionan los archivos de configuración de ruta. Dado un directorio llamado with_modules que contiene el archivo mymodule.py con esta declaración print que muestra cómo se importó el módulo:

with_modules/mymodule.py
import os
print('Loaded {} from {}'.format(
    __name__, __file__[len(os.getcwd()) + 1:])
)

Esta secuencia de comandos muestra cómo additedir() extiende la ruta de importación para que el intérprete pueda encontrar el módulo deseado.

site_addsitedir.py
import site
import os
import sys

script_directory = os.path.dirname(__file__)
module_directory = os.path.join(script_directory, sys.argv[1])

try:
    import mymodule
except ImportError as err:
    print('Could not import mymodule:', err)

print()
before_len = len(sys.path)
site.addsitedir(module_directory)
print('New paths:')
for p in sys.path[before_len:]:
    print(p.replace(os.getcwd(), '.'))  # shorten dirname

print()
import mymodule

Después de agregar el directorio que contiene el módulo a sys.path, la secuencia de comandos puede importar mymodule sin problemas.

$ python3 site_addsitedir.py with_modules

Could not import mymodule: No module named 'mymodule'

New paths:
./with_modules

Loaded mymodule from with_modules/mymodule.py

Los cambios de ruta por additedir() van más allá de simplemente agregar el argumento a sys.path. Si el directorio dado a additedir() incluye cualquier archivo que coincida con el patrón *.pth, se cargarán como archivos de configuración de ruta. Dada una estructura de directorios como la siguiente

with_pth
├── pymotw.pth
└── subdir
    └── mymodule.py

Si with_pth/pymotw.pth contiene

# Add a single subdirectory to the path.
./subdir

entonces se puede importar with_pth/subdir/mymodule.py agregando with_pth como directorio del sitio, aunque el módulo no esté en ese directorio porque tanto with_pth como with_pth/subdir se agregan a la ruta de importación.

$ python3 site_addsitedir.py with_pth

Could not import mymodule: No module named 'mymodule'

New paths:
./with_pth
./with_pth/subdir

Loaded mymodule from with_pth/subdir/mymodule.py

Si un directorio del sitio contiene múltiples archivos .pth, se procesan en orden alfabético.

$ ls -F multiple_pth

a.pth
b.pth
from_a/
from_b/

$ cat multiple_pth/a.pth

./from_a

$ cat multiple_pth/b.pth

./from_b

En este caso, el módulo se encuentra en multiple_pth/from_a porque a.pth se lee antes que b.pth.

$ python3 site_addsitedir.py multiple_pth

Could not import mymodule: No module named 'mymodule'

New paths:
./multiple_pth
./multiple_pth/from_a
./multiple_pth/from_b

Loaded mymodule from multiple_pth/from_a/mymodule.py

Personalizar la configuración del sitio

El módulo site también es responsable de cargar la personalización de todo el sitio definida por el propietario del sitio local en un módulo sitecustomize. Los usos de sitecustomize incluyen extender la ruta de importación y habilitar la cobertura, la creación de perfiles u otras herramientas de desarrollo.

Por ejemplo, esta secuencia de comandos sitecustomize.py extiende la ruta de importación con un directorio basado en la plataforma actual. La ruta específica de la plataforma en /opt/python se agrega a la ruta de importación, por lo que cualquier paquete instalado allí se puede importar. Un sistema como este es útil para compartir paquetes que contienen módulos de extensión compilados entre hosts en una red a través de un sistema de archivos compartido. Solo se necesita instalar la secuencia de comandos sitecustomize.py en cada host, y se puede acceder a los otros paquetes desde el servidor de archivos.

with_sitecustomize/sitecustomize.py
print('Loading sitecustomize.py')

import site
import platform
import os
import sys

path = os.path.join('/opt',
                    'python',
                    sys.version[:3],
                    platform.platform(),
                    )
print('Adding new path', path)

site.addsitedir(path)

Se puede usar una secuencia de comandos simple para mostrar que sitecustomize.py se importa antes de que Python comience a ejecutar su propio código.

with_sitecustomize/site_sitecustomize.py
import sys

print('Running main program from\n{}'.format(sys.argv[0]))

print('End of path:', sys.path[-1])

Dado que sitecustomize está destinado a la configuración de todo el sistema, debe instalarse en algún lugar de la ruta predeterminada (generalmente en el directorio site-packages). Este ejemplo establece PYTHONPATH explícitamente para garantizar que el módulo se recupere.

$ PYTHONPATH=with_sitecustomize python3 with_sitecustomize/sit\
e_sitecustomize.py

Loading sitecustomize.py
Adding new path /opt/python/3.6/Darwin-17.4.0-x86_64-i386-64bit
Running main program from
with_sitecustomize/site_sitecustomize.py
End of path: /opt/python/3.6/Darwin-17.4.0-x86_64-i386-64bit

Personalizar la configuración del usuario

Similar a sitecustomize, el módulo usercustomize se puede usar para establecer configuraciones específicas del usuario cada vez que se inicia el intérprete. usercustomize se carga después de sitecustomize, por lo que se pueden anular las personalizaciones de todo el sitio.

En entornos donde el directorio de inicio de un usuario se comparte en varios servidores que ejecutan diferentes sistemas operativos o versiones, el mecanismo de directorio de usuario estándar puede no funcionar para instalaciones de paquetes específicas del usuario. En estos casos, se puede utilizar un árbol de directorio específico de la plataforma.

with_usercustomize/usercustomize.py
print('Loading usercustomize.py')

import site
import platform
import os
import sys

path = os.path.expanduser(os.path.join('~',
                                       'python',
                                       sys.version[:3],
                                       platform.platform(),
                                       ))
print('Adding new path', path)

site.addsitedir(path)

Otra secuencia de comandos simple, similar al que se usa para sitecustomize, se puede usar para mostrar que usercustomize.py se importa antes de que Python comience a ejecutar otro código.

with_usercustomize/site_usercustomize.py
import sys

print('Running main program from\n{}'.format(sys.argv[0]))

print('End of path:', sys.path[-1])

Dado que usercustomize está destinado a la configuración específicas para un usuario, debe instalarse en algún lugar de la ruta predeterminada del usuario, pero no en la ruta de todo el sitio. El directorio predeterminado USER_BASE es una buena ubicación. Este ejemplo establece PYTHONPATH explícitamente para garantizar que el módulo se recupere.

$ PYTHONPATH=with_usercustomize python3 with_usercustomize/site\
_usercustomize.py

Loading usercustomize.py
Adding new path /Users/dhellmann/python/3.5/Darwin-15.5.0-x86_64\
-i386-64bit
Running main program from
with_usercustomize/site_usercustomize.py
End of path: /Users/dhellmann/python/3.5/Darwin-15.5.0-x86_64\
-i386-64bit

Cuando la función del directorio del sitio del usuario está deshabilitada, usercustomize no se importa, ya sea que se encuentre en el directorio del sitio del usuario o en otro lugar.

$ PYTHONPATH=with_usercustomize python3 -s with_usercustomize/s\
ite_usercustomize.py

Running main program from
with_usercustomize/site_usercustomize.py
End of path: /Users/dhellmann/Envs/pymotw35/lib/python3.5/site-
packages

Deshabilitar el módulo del sitio

Para mantener la compatibilidad con versiones de Python anteriores a la adición de la importación automática, el intérprete acepta una opción -S.

$ python3 -S site_import_path.py

Path prefixes:
   /Users/dhellmann/Envs/pymotw36/bin/..
   /Users/dhellmann/Envs/pymotw36/bin/..

/Users/dhellmann/Envs/pymotw36/bin/..

  lib/python3.6/site-packages
   exists : True
   in path: False

  lib/site-python
   exists : False
   in path: False

Ver también