En esta página se describe cómo instalar y usar servicios empaquetados antiguos con el runtime de Python 3 en el entorno estándar. Tu aplicación debe acceder a los servicios agrupados a través del SDK de servicios de App Engine para Python 3.
Antes de empezar
- Consulta la lista de APIs de servicios agrupados antiguos a las que puedes llamar en el tiempo de ejecución de Python.
- Antes de iniciar un proyecto de migración a Python 3, consulta la información general sobre la migración del entorno de ejecución y las consideraciones sobre la migración al usar servicios agrupados antiguos.
Instalar el SDK de servicios de App Engine
Para instalar el SDK de servicios de App Engine, sigue estos pasos:
Incluye el SDK en tu aplicación añadiendo la siguiente línea a tu archivo
requirements.txt
:appengine-python-standard>=1.0.0
Puedes encontrar el SDK en GitHub, en el repositorio
appengine-python-standard
, y en PyPI.Añade el siguiente código a tu secuencia de comandos principal de Python. Este código crea un middleware de WSGI que define las variables necesarias para habilitar las llamadas a la API.
Flask
from flask import Flask from google.appengine.api import wrap_wsgi_app app = Flask(__name__) app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
Django
from DJANGO_PROJECT_NAME.wsgi import application from google.appengine.api import wrap_wsgi_app app = wrap_wsgi_app(application)
Pirámide
from pyramid.config import Configurator from google.appengine.api import wrap_wsgi_app config = Configurator() # make configuration settings app = config.make_wsgi_app() app = wrap_wsgi_app(app)
WSGI
import google.appengine.api def app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield b'Hello world!\n' app = google.appengine.api.wrap_wsgi_app(app)
Añade la siguiente línea al archivo
app.yaml
antes de implementar tu aplicación:app_engine_apis: true
Para desplegar tu aplicación, usa el comando
gcloud app deploy
.
Consideraciones sobre la migración
Debes tener en cuenta lo siguiente si vas a migrar al tiempo de ejecución de Python 3 y tu aplicación usa servicios empaquetados antiguos.
Pruebas
Para probar localmente la función de los servicios agrupados antiguos en tu aplicación Python 3, usa el servidor de desarrollo local.
Al ejecutar el comando dev_appserver.py
, debe definir el argumento --runtime_python_path
para incluir una ruta al intérprete de Python 3.
Por ejemplo:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path=/usr/bin/python3
También puedes definir el argumento como una lista de pares [RUNTIME_ID]=[PYTHON_INTERPRETER_PATH]
separados por comas. Por ejemplo:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path="python27=/user/bin/python2.7,python3=/usr/bin/python3"
Compatibilidad con Pickle
Los servicios compartidos, como Memcache, Cloud NDB y deferred, usan el módulo pickle para serializar y compartir objetos de Python. Si tu entorno de App Engine usa tanto Python 2 como Python 3, lo cual es habitual durante una migración, debes asegurarte de que los objetos serializados compartidos escritos por una versión de Python se puedan reconstituir con la otra. Puedes consultar las directrices para implementar la compatibilidad entre versiones de pickle en la guía.
De forma predeterminada, Python 3 usa protocolos de serialización que no son compatibles con Python 2.
Esto puede provocar errores cuando tu aplicación intente reconstituir un objeto de Python
en un entorno de Python 2 que se haya escrito en un entorno de Python 3.
Para evitar este problema, define las siguientes variables de entorno en el archivo app.yaml
de tu aplicación Python 3 según sea necesario:
- En las aplicaciones que usan Memcache, incluidas las que usan NDB, define lo siguiente:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: 'True'
- En las aplicaciones que usan NDB para conectarse a Datastore, define lo siguiente:
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
- En el caso de las aplicaciones que usan la opción de diferir, define lo siguiente:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
En Python 2, los objetos string
contienen una secuencia de valores de bytes de 8 bits. En Python 3, los objetos string
contienen una secuencia de caracteres Unicode. De forma predeterminada, Python 3
pickle traduce un string
de Python 2 a Unicode interpretando el string
de Python 3
como ASCII. Esto puede provocar errores en los valores que estén fuera del intervalo de caracteres ASCII
de 0 a 127. Memcache permite anular esta asignación predeterminada.
from google.appengine.api import memcache
import six.moves.cPickle as pickle
def _unpickle_factory(file):
return pickle.Unpickler(file, encoding='latin1')
memcache.setup_client(memcache.Client(unpickler=_unpickle_factory))
La codificación latin1
define una asignación para cada uno de los 256 valores posibles de cada byte de un string
de Python 2. De esta forma, se evitan errores de decodificación. Sin embargo, si tu Python 2 string
contiene datos Unicode reales fuera del intervalo latin1
, como datos leídos de un archivo, cPickle no asignará los datos correctamente. Por lo tanto, es importante que actualices tu código de Python 2 para que contenga datos Unicode con objetos unicode
y no con objetos string
, en el caso de los objetos que serialices. En la guía de compatibilidad se
incluyen detalles sobre las actualizaciones necesarias.
El método descrito anteriormente para actualizar el código de Python 2 y generar serializaciones compatibles con Python 3 se aplica a serializaciones de corta duración, como las que se almacenan en Memcache. Es posible que tengas que actualizar o reescribir serializaciones de Python 2 de larga duración, como las almacenadas en Datastore, como parte de tu migración. Por ejemplo, es posible que la serialización escrita con
google.appengine.ext.ndb.model.PickleProperty
requiera una actualización.
Consulta la guía de compatibilidad para obtener más información sobre las limitaciones y los problemas menos habituales.
Frameworks web
webapp2
no se incluye ni se admite en Python 3, por lo que cualquier aplicación debe reescribirse para usar cualquier framework compatible con WSGI (como Flask).
Una estrategia de migración recomendada es sustituir primero el uso de webapp2
en tu aplicación Python 2.7 por Flask (o un framework web alternativo, como Django, Pyramid, Bottle o web.py) y seguir usando Python 2.7.
Después, cuando la aplicación actualizada sea estable, migra el código a Python 3 e impleméntalo y pruébalo con App Engine para Python 3.
Para ver ejemplos de cómo convertir aplicaciones de Python 2.7 que usan webapp2
para usar el framework Flask, puedes consultar estos recursos adicionales.
Usar controladores
Una aplicación de Python 3 solo puede tener una secuencia de comandos asociada, por lo que, si tu
app.yaml
tiene varios controladores script
que asignan URLs a diferentes secuencias de comandos,
tendrás que combinar esas secuencias de comandos en una que gestione el enrutamiento de URLs.
En el siguiente ejemplo se muestran las diferencias de los controladores en el archivo app.yaml
de los respectivos tiempos de ejecución.
Python 2
runtime: python27 api_version: 1 threadsafe: true handlers: - url: / script: home.app - url: /index\.html script: home.app - url: /stylesheets static_dir: stylesheets - url: /(.*\.(gif|png|jpg))$ static_files: static/\1 upload: static/.*\.(gif|png|jpg)$ - url: /admin/.* script: admin.app login: admin - url: /.* script: not_found.app
Python 3
runtime: python313
app_engine_apis: true
handlers:
- url: /stylesheets
static_dir: stylesheets
- url: /(.*\.(gif|png|jpg))$
static_files: static/\1
upload: static/.*\.(gif|png|jpg)$
- url: /admin/.*
script: auto
login: admin
Tu aplicación Python 3 debe gestionar el enrutamiento de URLs (por ejemplo, con decoradores de Flask).
Si quieres usar varios controladores script
con patrones de URL diferentes o si quieres usar otros atributos en tus controladores, cada controlador debe especificar script: auto
.
También puedes anular el comportamiento de inicio predeterminado especificando un campo entrypoint
en el archivo app.yaml
.
Consulta las descripciones generales de Blobstore, Deferred y Mail para obtener más información sobre cómo usar controladores específicos.
Seguridad de los hilos
Se da por hecho que las aplicaciones son seguras para subprocesos. Las llamadas a la API deben hacerse en el hilo de la solicitud. Si usas una API de servicios agrupados antigua cuando se inicia la aplicación, se pueden producir errores de seguridad.
Para obtener más información, consulta Errores de seguridad al usar servicios empaquetados antiguos para Python.
Cómo utilizar la extracción de URL
Para usar URL Fetch para Python, debes llamar explícitamente a la biblioteca URL Fetch.
Si tu aplicación de Python 3 usa la API URL Fetch, el encabezado de solicitud X-Appengine-Inbound-Appid
se añade cuando tu aplicación envía una solicitud a otra aplicación de
App Engine. De esta forma, la aplicación receptora puede verificar la identidad de la aplicación que llama. Para obtener más información, consulta Migrar solicitudes salientes.
Ejemplo (App Engine ndb
)
A continuación, se muestra una aplicación básica de Python 2 que registra las visitas a una página mediante App Engine ndb
para acceder a Datastore. Su aplicación equivalente es una aplicación de Python 3 en la que webapp2
usage se ha sustituido por Flask y se han implementado los cambios necesarios descritos anteriormente para
acceder a los servicios empaquetados en Python 3.
Python 2 (webapp2
)
Python 3 (Flask)
Ambas aplicaciones se encuentran en el repositorio de código abierto del contenido de migración de Python App Engine (ejemplos de código, vídeos y codelabs), concretamente en las carpetas mod0
y mod1b
, respectivamente.