for - ¿Cómo administro bibliotecas de Python de terceros con Google App Engine?(virtualenv? pip?)
google app engine python (6)
¿Qué tal simplemente?
$ pip install -r requirements.txt -t <your_app_directory/lib>
Crear / editar <your_app_directory>/appengine_config.py
:
"""This file is loaded when starting a new application instance."""
import sys
import os.path
# add `lib` subdirectory to `sys.path`, so our `main` module can load
# third-party libraries.
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ''lib''))
ACTUALIZAR:
Google actualizó su muestra a appengine_config.py
, como:
from google.appengine.ext import vendor
vendor.add(''lib'')
Nota: A pesar de que su ejemplo tiene .gitignore
ignorando el directorio lib/
, usted todavía necesita mantener ese directorio bajo control de fuente si usa el método de implementación de git-push
.
¿Cuál es la mejor estrategia para administrar bibliotecas de Python de terceros con Google App Engine?
Digamos que quiero usar Flask, un framework webapp. Una entrada de blog dice que hacer esto, lo que no parece correcto:
$ cd /tmp/
$ wget http://pypi.python.org/packages/source/F/Flask/Flask-0.6.1.tar.gz
$ tar zxf Flask-0.6.1.tar.gz
$ cp -r Flask-0.6.1/flask ~/path/to/project/
(... repeat for other packages ...)
Debe haber una forma mejor de administrar código de terceros, especialmente si quiero rastrear versiones, probar actualizaciones o si dos bibliotecas comparten un subdirectorio. Sé que Python puede importar módulos desde archivos zip y que pip puede funcionar con un maravilloso archivo REQUIREMENTS, y he visto que pip tiene un comando zip
para usar con GAE.
(Nota: hay un puñado de preguntas similares, 1 , 2 , 3 , 4 , 5 , pero son específicas de cada caso y realmente no responden a mi pregunta).
Así es como lo hago:
- proyecto
- .Pitón
- compartimiento
- lib
- python2.5
- paquetes de sitio
- <pip instale paquetes aquí>
- paquetes de sitio
- python2.5
- incluir
- src
- app.yaml
- index.yaml
- main.yaml
- <enlace simbólico de los paquetes instalados en pip en ../lib/python2.5/site-packages
El directorio del project
es el directorio de nivel superior donde se encuentra el virtualenv. Obtengo el virtualenv usando los siguientes comandos:
cd project
virtualenv -p /usr/bin/python2.5 --no-site-packages --distribute .
El directorio src
es donde va todo tu código. Cuando implementa su código en GAE, * solo * despliega aquellos en el directorio src y nada más. El appcfg.py
resolverá los enlaces simbólicos y copiará los archivos de la biblioteca a GAE por usted.
No instalo mis bibliotecas como archivos zip principalmente por conveniencia en caso de que necesite leer el código fuente, lo que sucede es que hago muchas cosas solo por curiosidad. Sin embargo, si realmente desea comprimir las bibliotecas, coloque el siguiente fragmento de código en main.py
import sys
for p in [''librarie.zip'', ''package.egg''...]:
sys.path.insert(0, p)
Después de esto, puede importar sus paquetes comprimidos como de costumbre.
Una cosa a tener en cuenta es setuptools '' pkg_resources.py
. Copié eso directamente en mi directorio src
para que mis otros paquetes enlazados puedan usarlo. Tenga cuidado con cualquier cosa que use entry_point
s. En mi caso, estoy usando Toscawidgets2 y tuve que profundizar en el código fuente para conectar manualmente las piezas. Puede ser molesto si tienes muchas bibliotecas que dependen de entry_point
.
Nota: esta respuesta es específica para Flask en Google App Engine.
Consulte el proyecto del matraz-appengine-template para ver un ejemplo de cómo hacer que las extensiones de Flask funcionen en App Engine. https://github.com/kamalgill/flask-appengine-template
Coloque la extensión en la carpeta del paquete de espacio de nombres en src / packages / flaskext y ya está todo listo. https://github.com/kamalgill/flask-appengine-template/tree/master/src/lib/flaskext
Los paquetes que no son Flask se pueden colocar en la carpeta src / packages como archivos zip, huevecillos o paquetes descomprimidos, ya que la plantilla del proyecto incluye el fragmento sys.path.insert () publicado anteriormente.
Recientemente creé una herramienta para esto llamada gaenv. Sigue un formato de requirements.txt, pero no lo instala, puede instalarlo con pip install -r requirements.txt y luego ejecutar la herramienta de línea de comandos gaenv.
$ pip install -r requirements.txt
$ gaenv
Esto crea enlaces simbólicos automáticamente, puedes instalar gaenv en tu virtualenv también y ejecutar el binario desde allí. Aquí hay una publicación en el blog sobre esto:
http://blog.altlimit.com/2013/06/google-app-engine-virtualenv-tool-that.html
también en github
Yo prefiero la buildout .
Configura dependencias en setup.py en su proyecto o buildout.cfg, fija las versiones en buildout.cfg y especifica qué paquetes no están disponibles en GAE y deben incluirse en packages.zip. rod.recipe.appengine copiará los paquetes necesarios en packages.zip, y siempre que inserte packages.zip en sys.path, se pueden importar en cualquier lugar.
También puede usar las horquillas de github si el paquete que necesita no está en pypi
find-links =
https://github.com/tesdal/pusher_client_python/tarball/rewrite#egg=pusher-2.0dev2
[versions]
pusher = 2.0dev2
y todas estas configuraciones y dependencias están versionadas en git.
En lugar de preguntarse qué copia de Flask está actualmente incluida en su árbol de código fuente y tal vez copiada en el control de su versión (o que requiera que los nuevos desarrolladores desempaqueten y actualicen manualmente), simplemente verifique la versión en buildout.cfg. Si desea una versión nueva, cambie buildout.cfg y vuelva a ejecutar buildout.
También puede usarlo para insertar variables en las plantillas de archivos de configuración, como configurar la id de appspot y la versión en app.yaml si tiene un servidor de etapas con staging.cfg y así sucesivamente.
La solución de Wernight es la más cercana a la práctica actual en la aplicación oficial de ejemplo Flask , que ya he mejorado cambiando la llamada site.addsitedir()
a site.addsitedir()
para permitir paquetes de espacio de nombres procesando su asistente .pth
archivos .pth
(que son importantes para marcos como Pyramid).
Hasta ahora todo va bien, pero eso agrega el directorio a la ruta y, por lo tanto, pierde la oportunidad de anular las bibliotecas incluidas (como WebOb y solicitudes) con las versiones más recientes.
Lo que se necesita entonces en appengine_config.py
(y estoy tratando de que este cambio sea aceptado en los repos oficiales también) es el siguiente:
"""This file is loaded when starting a new application instance."""
import os.path
import site.addsitedir
import sys.path
dirname = ''lib''
dirpath = os.path.join(os.path.dirname(__file__), dirname)
# split path after 1st element (''.'') so local modules are always found first
sys.path, remainder = sys.path[:1], sys.path[1:]
# add `lib` subdirectory as a site directory, so our `main` module can load
# third-party libraries.
site.addsitedir(dirpath)
# append the rest of the path
sys.path.extend(remainder)
La versión final de este código puede ocultarse en un módulo vendor.py
y llamarse como insertsitedir(index, path)
u otra variación, como se puede ver en la discusión que acompaña a esta solicitud de extracción , pero la lógica es más o menos cómo funcionará independientemente, para permitir una simple pip install -r requirements.txt -t lib/
para trabajar con todos los paquetes, incluidos los del espacio de nombres, y aún permitir anular las bibliotecas incluidas con las nuevas versiones, ya que hasta ahora no he podido encuentra una alternativa más simple .