En esta página se describen las medidas necesarias para actualizar tu aplicación Python al entorno de ejecución de Python 2.7. Después de seguir este tutorial, tu aplicación podrá aprovechar las numerosas funciones nuevas del entorno de ejecución de Python 2.7, como el multihilo, el motor de plantillas Jinja2, el acceso y la subida de bytecode, y varias bibliotecas de terceros incluidas.
Requisitos previos y consideraciones
Para usar Python 2.7, una aplicación debe cumplir los siguientes requisitos:
- Si la aplicación usa Django, debe usar la versión 1.2 o una posterior. Consulta la documentación de Django para obtener más información sobre la actualización.
- Si quieres usar solicitudes simultáneas, la aplicación debe usar controladores de secuencias de comandos de Web Server Gateway Interface (WSGI), tal como se explica en el artículo Usar WSGI.
Además de cumplir estos requisitos generales, debes usar versiones específicas de algunas funciones de App Engine y bibliotecas de terceros. Asegúrate de actualizar las versiones que incluyas e importes en tu aplicación, y prueba la aplicación a fondo después de actualizarla. En la siguiente lista se identifican los principales problemas de compatibilidad y se indican recursos adicionales para resolverlos:
- Rendimiento: el rendimiento de la aplicación puede cambiar después de actualizar a Python 2.7. Si experimentas un aumento de la latencia de respuesta, puedes aumentar la clase de instancia del frontend y habilitar las solicitudes simultáneas. Las solicitudes simultáneas permiten que tu aplicación funcione más rápido con un coste de instancia más bajo en instancias más grandes. Para obtener más información, consulta Gestión de solicitudes en instancias.
- Django: Debes usar Django 1.2 o una versión posterior con Python 2.7. Para obtener información sobre cómo actualizar, consulta las notas de la versión de Django.
- PyCrypto
Crypto.Util.randpool
ha quedado obsoleto. Ahora se utilizaCrypto.Random
. Para obtener más información, consulta Qué hacer con RandomPool. webapp
: las plantillas de aplicaciones web están obsoletas en Python 2.7. En su lugar, puedes usar directamente plantillas de Django, jinja2 u otro motor de plantillas que elijas.- WebOb Python 2.7 es compatible con la versión 1.1 de WebOb. Esta versión no es totalmente retrocompatible con la versión anterior (0.9). Si la aplicación usa WebOb, debes probarla a fondo para detectar cualquier error que se produzca como resultado de la actualización.
- zipimport: Python 2.7 no admite zipimport, pero Python 2.7 puede importar de forma nativa desde archivos .zip.
- simplejson: Python 2.7 no admite simplejson, pero incluye el módulo json de la biblioteca estándar, que es equivalente y mucho más rápido.
Solicitudes simultáneas y WSGI
La función de Python 2.7 que más afecta al diseño y al rendimiento de tu aplicación es su compatibilidad con aplicaciones multiproceso que pueden gestionar solicitudes simultáneas. La capacidad de gestionar solicitudes simultáneas mejora el uso, lo que puede aumentar significativamente el rendimiento de tu aplicación, especialmente en el caso de las aplicaciones que utilizan clases de instancias superiores que aprovechan varios núcleos de CPU.
Para habilitar el multihilo, las aplicaciones deben pasar del enfoque basado en la interfaz de puerta de enlace común (CGI) de los tiempos de ejecución de Python anteriores a un enfoque basado en la interfaz de puerta de enlace del servidor web (WSGI). Esto se debe a que las secuencias de comandos CGI, que se diseñaron para gestionar las solicitudes de forma secuencial, dependen de las variables de entorno para acceder a los flujos de entrada y salida.
Aunque el modelo WSGI para gestionar solicitudes ofrece a las aplicaciones un acceso más directo a los flujos de entrada y salida (lo que permite que se realicen solicitudes simultáneas), la gestión de varias solicitudes en paralelo puede provocar condiciones de carrera cuando la lógica de un controlador de solicitudes se basa en datos con un ámbito superior al local o interactúa con ellos, como el estado de la aplicación. Por este motivo, es importante codificar de forma defensiva para hacer frente a las condiciones de carrera y asegurarse de que la nueva aplicación WSGI sea segura para los subprocesos.
Consulta más información sobre cómo hacer que tu aplicación sea segura para subprocesos.
Actualizar app.yaml
Python 2.7 requiere un elemento de configuración runtime
especial en el encabezado de app.yaml
.
Ten en cuenta que el elemento threadsafe: [ true | false ]
es obligatorio para las aplicaciones de Python 2.7. Si true
, App Engine envía las solicitudes simultáneamente; si false
, las envía de forma secuencial. El siguiente encabezado app.yaml
permite enviar solicitudes simultáneas:
application: myapp version: 1 runtime: python27 api_version: 1 threadsafe: true ...
Usar WSGI
El tiempo de ejecución de Python 2.7 te permite ejecutar directamente una aplicación de interfaz de pasarela de servidor web (WSGI) en lugar de usar el adaptador run_wsgi_app
para ejecutar el programa como una secuencia de comandos CGI.
Para ello, sustituye el controlador CGI (por ejemplo, myapp.py
) en app.yaml
por un nombre de aplicación WSGI (por ejemplo, myapp.app
).
... handlers: - url: /.* script: myapp.app ...
También debes mover el objeto de aplicación WSGI al ámbito global:
import webapp2 class MainPage(webapp2.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Hello, WebApp World!') app = webapp2.WSGIApplication([('/', MainPage)]) """ Old code: def main(): run_wsgi_app(app) if __name__ == '__main__': main() """
Aun así, puedes especificar controladores de secuencias de comandos CGI en
app.yaml
. Sin embargo, las solicitudes gestionadas por secuencias de comandos CGI se procesan
de forma secuencial, no simultánea. Además, no puedes tener un archivo
app.yaml
que combine secuencias de comandos CGI y aplicaciones WSGI, y no puedes definir threadsafe
como true
si defines algún controlador CGI.
Algunas convenciones de los entornos de ejecución de Python anteriores, como el uso de
main()
y la comprobación de
__name__ == 'main'
,
ya no están disponibles. Estas medidas ayudaban a que las secuencias de comandos CGI del pasado permanecieran en la caché, pero ahora que ejecutas aplicaciones WSGI directamente, estos pasos ya no son necesarios.
Usar el directorio raíz de la aplicación
En Python 2.5, las secuencias de comandos CGI se ejecutaban con el directorio de trabajo actual definido en el directorio que contenía la secuencia de comandos. Esto ha cambiado en Python 2.7. Con WSGI, el directorio de trabajo actual al principio del ciclo de vida del controlador de solicitudes es el directorio raíz de la aplicación.
Revisa el código de tu aplicación y asegúrate de que todos los controladores estén escritos para que el directorio de trabajo actual sea la raíz de la aplicación.
Configurar bibliotecas
El tiempo de ejecución de Python 2.7 incluye algunos módulos de terceros. Algunas están disponibles de forma predeterminada, mientras que otras solo se pueden usar si se configuran. Puedes especificar qué versión quieres usar.
libraries: - name: PIL version: "1.1.7" - name: webob version: "1.1.1"
Puedes especificar que la aplicación debe usar la versión más reciente del módulo. Esto resulta útil si estás desarrollando una aplicación que aún no tiene usuarios, ya que no tendrás que hacer un seguimiento de las versiones nuevas. Sin embargo, si tu aplicación se está usando activamente, ten cuidado: puede que te sorprenda que tu aplicación empiece a usar una nueva versión de biblioteca que no sea compatible con versiones anteriores. Para usar la versión más reciente, sigue estos pasos:
libraries: - name: PIL version: latest
Para ver una lista de las bibliotecas admitidas, consulta Bibliotecas de terceros.
Hacer que tu aplicación sea segura para subprocesos
Gestionar solicitudes simultáneas es sencillo si cada controlador solo interactúa con variables dentro de su ámbito. Sin embargo, la situación se complica rápidamente si un controlador modifica los recursos mientras otro los lee. Asegurarse de que tu aplicación se comporta como se espera, aunque varias solicitudes puedan manipular los mismos datos e interferir entre sí, se conoce como "threadsafe".
La regla principal a la hora de diseñar una aplicación que sea segura para subprocesos es limitar el uso de recursos compartidos (como información de estado o variables globales) tanto como sea posible. Sin embargo, normalmente no es posible descartar por completo su uso, y es ahí donde entran en juego los mecanismos de sincronización, como los objetos de bloqueo.
En Python 2.7, tienes acceso a la biblioteca de threading de Python, que te permite declarar un bloqueo en un bloque de lógica que obliga a que el código interno se ejecute de forma secuencial en lugar de simultánea. Echa un vistazo al siguiente código:
class Configuration(ndb.Model): some_config_data = ndb.StringProperty() _config_cache = None _config_lock = threading.Lock() @classmethod def get_config(cls): with cls._config_lock: if not cls._config_cache: cls._config_cache = cls.get_by_id('config') return cls._config_cache
Este código muestra la creación de una caché de
algunas variables de configuración globales en una variable llamada _config_cache
. En este caso, el uso de un objeto de bloqueo llamado _config_lock
asegura que la comprobación de un _config_cache
preexistente se comporte de forma fiable. De lo contrario, esta variable podría perder tiempo haciendo varios viajes a Datastore para definir la misma variable varias veces con los mismos datos, ya que todas las solicitudes simultáneas han detectado que _config_cache
estaba vacío.
No elijas usar bloqueos a la ligera. Un bloqueo obliga a bloquear cualquier otro hilo que ejecute este método. Esto puede suponer un cuello de botella para el rendimiento.
Actualizar una aplicación a webapp2
Nota: Si no usas webapp
como controlador de solicitudes, puedes saltarte esta sección.
El framework web incluido en el entorno de ejecución de Python 2.7 se ha actualizado de webapp
a webapp2. Entre otras cosas, webapp2
añade una mejor gestión de excepciones y de rutas de URIs, un objeto de respuesta con todas las funciones y un mecanismo de envío más flexible.
Las plantillas webapp
se han
desactivado. En su lugar, puedes usar Jinja2, Django o el sistema de plantillas que quieras (siempre que esté escrito en Python puro).
En App Engine, webapp2
se ha asignado a webapp
y webapp2
es retrocompatible. Sin embargo, después de actualizar, debes probar a fondo tu aplicación y familiarizarte con la nueva sintaxis y las nuevas funciones de webapp2
, en lugar de seguir usando la compatibilidad con versiones anteriores.
¡Y ya has completado la actualización!
Una vez que hayas subido la aplicación, debes probarla a fondo para asegurarte de que es compatible con versiones anteriores. Si tienes problemas, consulta los foros.