En esta página, se describe cómo instalar y usar los servicios agrupados en paquetes heredados con el entorno de ejecución de Python 3 para el entorno estándar. Tu aplicación debe acceder a los servicios en paquetes a través del SDK de servicios de App Engine para Python 3.
Antes de comenzar
- Consulta la lista de APIs de servicios agrupados en paquetes heredados que puedes llamar en el entorno de ejecución de Python.
- Antes de comenzar un proyecto de migración a Python 3, consulta la descripción general de la migración del entorno de ejecución y las consideraciones de migración cuando uses los servicios agrupados en paquetes heredados.
Instala el SDK de servicios de App Engine
Para instalar el SDK de servicios de App Engine, sigue estos pasos:
Para incluir el SDK con tu app, agrega 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.Agrega el siguiente código a tu secuencia de comandos principal de Python. Este código crea el middleware WSGI que configura las variables necesarias para habilitar tus 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)
Pyramid
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)
Agrega la siguiente línea a tu archivo
app.yaml
antes de implementar tu app:app_engine_apis: true
Para implementar la app, usa el comando
gcloud app deploy
.
Consideraciones sobre la migración
Debes tener en cuenta las siguientes consideraciones si migras al entorno de ejecución de Python 3 y tu app usa los servicios agrupados en paquetes heredados.
Prueba
Para probar localmente la funcionalidad de servicios en paquetes heredados en tu app de Python 3, usa el servidor de desarrollo local.
Cuando ejecutas el comando dev_appserver.py
, debes configurar el argumento --runtime_python_path
para que incluya 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 establecer el argumento en una lista separada por comas de pares [RUNTIME_ID]=[PYTHON_INTERPRETER_PATH]
. 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 diferidos, usan el módulo pickle para serializar y compartir objetos de Python. Si tu entorno de App Engine usa Python 2 y 3, que son comunes durante una migración, debes asegurarte de que los objetos compartidos serializados escritos por una versión de Python se puedan reducir por la otra. Puedes encontrar asesoramiento sobre la implementación de la compatibilidad con serialización de versiones cruzadas en la guía.
De forma predeterminada, Python 3 usa protocolos de serialización que no son compatibles con Python 2.
Esto puede causar fallas cuando la app intenta reconstituir un objeto de Python en un entorno de Python 2 que se escribió en un entorno de Python 3.
Para evitar este problema, configura las siguientes variables de entorno en el archivo app.yaml
de tu app de Python 3 según sea necesario:
- Para las apps que usan Memcache, incluidas las que usan NDB, configura:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: 'True'
- En el caso de las apps que usan NDB para conectarse a Datastore, configura lo siguiente:
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
- Para las apps que usan aplazamientos, configura lo siguiente:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
En Python 2, los objetos string
contienen una secuencia de valores de byte de 8 bits. En Python 3, los objetos string
contienen una secuencia de caracteres Unicode. De forma predeterminada, el pickle de Python 3 traduce una string
de Python 2 a unicode mediante la interpretación de la string
de Python 3 como ASCII. Esto puede generar errores para los valores fuera del rango de caracteres ASCII de 0 a 127. Memcache admite la anulación de 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 en un string
de Python 2. Esto evita los errores de decodificación. Sin embargo, si el string
de Python 2 contiene datos reales de Unicode fuera del rango latin1
, como los datos leídos de un archivo, cPickle no asignará los datos de forma correcta. Por lo tanto, es importante que actualices tu código de Python 2 para conservar los datos Unicode con objetos unicode
y no objetos string
, para los objetos que uses con Pickle. La guía de compatibilidad incluye detalles sobre las actualizaciones necesarias.
El método descrito antes para actualizar tu código de Python 2 que permite producir serializaciones compatibles de Python 3, aborda las serializaciones de corta duración, como las almacenadas en Memcache. Es posible que debas actualizar o reescribir las serializaciones de Python 2 de larga duración, como las almacenadas en Datastore como parte de la migración. Por ejemplo, la serialización escrita con google.appengine.ext.ndb.model.PickleProperty
puede requerir 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 admite en Python 3, por lo que cualquier aplicación debe volver a escribirse para usar cualquier marco de compatibilidad con WSGI (como Flask).
Una estrategia de migración recomendada es reemplazar primero el uso de webapp2
en tu app de Python 2.7 con Flask (o un framework web alternativo, como Django, Pyramid, Bottle o web.py) mientras se permanece en Python 2.7.
Luego, cuando tu app actualizada sea estable, migra el código a Python 3 y, luego, impleméntalo y pruébalo con App Engine para Python 3.
Si quieres obtener ejemplos sobre cómo convertir las apps de Python 2.7 que usan webapp2
para usar el framework de Flask, puedes consultar estos recursos adicionales.
Usa 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 URL a diferentes secuencias de comandos, deberás combinar esas secuencias de comandos en una que administre el enrutamiento de la URL.
En el siguiente ejemplo, se muestran las diferencias del controlador en el archivo app.yaml
para los entornos de ejecución respectivos.
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: python312
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 de Python 3 debe controlar el enrutamiento de URL (por ejemplo, con los decoradores de Flask).
Si deseas usar varios controladores script
con diferentes patrones de URL o
si deseas usar otros atributos en tus controladores, cada controlador debe
especificar script: auto
.
También puedes anular el comportamiento de inicio predeterminado si especificas un campo entrypoint
en el archivo app.yaml
.
Consulta las descripciones generales de Blobstore, Diferido y Correo electrónico para obtener más información sobre cómo usar controladores específicos.
Seguridad de subprocesos
Se supone que las aplicaciones son seguras para los subprocesos. Se deben realizar llamadas a la API en el subproceso de la solicitud. Esto puede generar errores de seguridad si usas una API de servicios agrupados en paquetes heredados cuando se inicia la aplicación.
Si deseas obtener más información, consulta Errores de seguridad que surgen al usar servicios agrupados en paquetes heredados para Python.
Usa la recuperación de URL
Si deseas usar la recuperación de URL para Python, debes llamar de forma explícita a la biblioteca de recuperación de URL.
Si tu app de Python 3 usa la API de URL Fetch, se agregará el encabezado de solicitud X-Appengine-Inbound-Appid
cuando la app envíe una solicitud a otra app de App Engine. Esto permite que la app receptora verifique la identidad de la app que realiza la llamada. Para obtener más información, consulta Migra solicitudes salientes.
Ejemplo (ndb
de App Engine)
A continuación, se muestra una app básica de Python 2 que registra las visitas a páginas mediante ndb
de App Engine para acceder a Datastore. Su complemento es una aplicación equivalente de Python 3 en la que Flask reemplazó el uso de webapp2
, y se implementaron los cambios necesarios descritos antes para acceder a los servicios agrupados en Python 3.
Python 2 (webapp2
)
Python 3 (Flask)
Ambas apps se pueden encontrar en el repositorio de código abierto del contenido de migración de App Engine en Python (muestras de código, videos y codelabs), en particular en las carpetas mod0
y mod1b
, respectivamente.