Questa pagina descrive come installare e utilizzare i servizi in bundle legacy con il runtime Python 3 per l'ambiente standard. La tua app deve accedere ai servizi in bundle tramite l'SDK dei servizi App Engine per Python 3.
appengine-python-standard>=1.0.0
Prima di iniziare
- Consulta l'elenco delle API dei servizi in bundle legacy che puoi chiamare nel runtime Python.
- Prima di avviare un progetto di migrazione a Python 3, consulta la panoramica della migrazione del runtime e le considerazioni sulla migrazione quando utilizzi i servizi in bundle legacy.
Installazione dell'SDK dei servizi App Engine
Per installare l'SDK dei servizi App Engine:
Includi l'SDK nella tua app aggiungendo la seguente riga al file
requirements.txt:appengine-python-standard>=1.0.0Puoi trovare l'SDK su GitHub nel
appengine-python-standardrepository, e su PyPI.Aggiungi il seguente codice nello script Python principale. Questo codice crea un middleware WSGI che imposta le variabili necessarie per abilitare le chiamate 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)Aggiorna il file
app.yamlper specificare uno o più servizi in bundle legacy. Ad esempio:app_engine_bundled_services: - datastore_v3 - memcache - userSe utilizzi funzionalità come
login: adminnella sezionehandlersdel fileapp.yaml, abilita l'API Users configurando l'impostazioneusernell'elencoapp_engine_bundled_services.Per eseguire il deployment dell'app, utilizza il
gcloud app deploycomando.
Considerazioni sulla migrazione
Se esegui la migrazione al runtime Python 3 e la tua app utilizza i servizi in bundle legacy, devi tenere presente le seguenti considerazioni.
Test
Per testare localmente la funzionalità dei servizi in bundle legacy nella tua
app Python 3, utilizza il
server di sviluppo locale.
Quando esegui il comando dev_appserver.py, devi impostare l'argomento --runtime_python_path in modo da includere un percorso all'interprete Python 3.
Ad esempio:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path=/usr/bin/python3
Puoi anche impostare l'argomento su un elenco separato da virgole di
[RUNTIME_ID]=[PYTHON_INTERPRETER_PATH] coppie. Ad esempio:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path="python27=/user/bin/python2.7,python3=/usr/bin/python3"
Compatibilità con Pickle
I servizi condivisi, tra cui Memcache, Cloud NDB e Deferred utilizzano il modulo pickle per serializzare e condividere gli oggetti Python. Se il tuo ambiente App Engine utilizza sia Python 2 sia Python 3, cosa comune durante una migrazione, devi assicurarti che gli oggetti serializzati condivisi scritti da una versione di Python possano essere ricostituiti dall'altra. Puoi trovare indicazioni sull'implementazione della compatibilità con pickle tra le versioni nel la guida.
Per impostazione predefinita, Python 3 utilizza protocolli di pickling non supportati in Python 2.
Ciò può causare errori quando l'app tenta di ricostituire un oggetto Python in un ambiente Python 2 scritto in un ambiente Python 3.
Per evitare questo problema, imposta le seguenti
variabili di ambiente
nel file app.yaml per l'app Python 3, se necessario:
- Per le app che utilizzano Memcache, incluse quelle che utilizzano NDB, imposta:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: 'True' - Per le app che utilizzano NDB per connettersi a Datastore, imposta:
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True' - Per le app che utilizzano Deferred, imposta:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
In Python 2, gli oggetti string contengono una sequenza di valori di byte a 8 bit. In Python 3, gli oggetti string contengono una sequenza di caratteri Unicode. Per impostazione predefinita, pickle di Python 3 traduce una string di Python 2 in Unicode interpretando la string di Python 3 come ASCII. Ciò può causare errori per i valori al di fuori dell'intervallo di caratteri ASCII da 0 a 127. Memcache supporta la sostituzione di questo mapping predefinito.
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 codifica latin1 definisce un mapping per ognuno dei 256 valori possibili di ogni byte in una string di Python 2. In questo modo si evitano errori di decodifica. Tuttavia, se la string di Python 2 contiene dati Unicode effettivi al di fuori dell'intervallo latin1, ad esempio dati letti da un file, cPickle non mapperà correttamente i dati. Pertanto, è importante aggiornare il codice Python 2 in modo che contenga dati Unicode con oggetti unicode e non oggetti string per gli oggetti che esegui con pickle. La guida alla compatibilità
include dettagli sugli aggiornamenti necessari.
Il metodo descritto in precedenza per aggiornare il codice Python 2 in modo da produrre serializzazioni compatibili con Python 3 riguarda le serializzazioni di breve durata, ad esempio quelle archiviate in Memcache. Potresti dover aggiornare o riscrivere le serializzazioni Python 2 di lunga durata, ad esempio quelle archiviate in Datastore nell'ambito della migrazione. Ad esempio, la serializzazione scritta utilizzando
google.appengine.ext.ndb.model.PickleProperty
potrebbe richiedere un upgrade.
Per saperne di più sulle limitazioni e sui problemi meno comuni, consulta la guida alla compatibilità.
Framework web
webapp2 non è in bundle né supportato in Python 3, quindi qualsiasi applicazione deve
essere riscritta per utilizzare qualsiasi framework compatibile con WSGI (come
Flask).
Una strategia di migrazione consigliata consiste nel sostituire prima l'utilizzo di webapp2 in
nell'app Python 2.7 con Flask (o un framework web alternativo come
Django,
Pyramid,
Bottle o
web.py), rimanendo su Python 2.7.
Poi, quando l'app aggiornata è stabile, esegui la migrazione del codice a Python 3, esegui il deployment e testa utilizzando App Engine per Python 3.
Per esempi di come convertire le app Python 2.7 che utilizzano webapp2
per utilizzare il framework Flask, puoi consultare
queste risorse aggiuntive.
Utilizzo dei gestori
Un'app Python 3 può avere un solo script associato, quindi se app.yaml ha più gestori script che mappano gli URL a script diversi, dovrai combinarli in uno che gestisca il routing degli URL.
L'esempio seguente mostra le differenze tra i gestori nel file app.yaml per i rispettivi runtime.
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: python314
app_engine_bundled_services:
- datastore_v3
- memcache
- user
...
#list your bundled services
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
L'app Python 3 deve gestire il routing degli URL (ad esempio, con i decoratori Flask).
Se vuoi utilizzare più script gestori con pattern URL diversi o
se vuoi utilizzare altri attributi nei gestori, ogni gestore deve
specificare script: auto.
Puoi anche sostituire il comportamento di avvio predefinito by
specificando un entrypoint field
in your app.yaml file.
Per saperne di più su come utilizzare gestori specifici, consulta le panoramiche di Blobstore, Deferred, e Mail.
Thread safety
Si presume che le app siano thread-safe. Le chiamate API devono essere effettuate sul thread della richiesta. Se utilizzi un'API dei servizi in bundle legacy all'avvio dell'app, possono verificarsi errori di sicurezza.
Per saperne di più, consulta Errori di sicurezza durante l'utilizzo dei servizi in bundle legacy per Python.
Utilizzo di URL Fetch
Per utilizzare URL Fetch per Python, devi chiamare esplicitamente la libreria URL Fetch.
Se l'app Python 3 utilizza l'API URL Fetch, l'intestazione della richiesta X-Appengine-Inbound-Appid viene aggiunta quando l'app invia una richiesta a un'altra app App Engine. In questo modo, l'app ricevente può verificare l'identità dell'app chiamante. Per saperne di più, consulta
Eseguire la migrazione delle richieste in uscita.
Esempio (App Engine ndb)
Di seguito è riportata un'app Python 2 di base che registra le visite alle pagine utilizzando App Engine ndb per accedere a Datastore. La sua controparte è un'app Python 3 equivalente in cui l'utilizzo di webapp2 è stato sostituito da Flask e sono state implementate le modifiche richieste descritte sopra per accedere ai servizi in bundle in Python 3.
Python 2 (webapp2)
Python 3 (Flask)
Entrambe queste app sono disponibili nel repository open source per i contenuti di migrazione di Python
App Engine (esempi di codice,
video,
codelab), in particolare nelle cartelle mod0
e mod1b rispettivamente.