Questa pagina descrive come installare e utilizzare i servizi legacy in bundle con il runtime Python 3 per l'ambiente standard. L'app deve accedere ai servizi in bundle tramite l'SDK per i servizi App Engine per Python 3.
Prima di iniziare
- Consulta l'elenco delle API dei servizi in bundle legacy che puoi chiamare nel runtime Python.
- Prima di iniziare 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 precedenti.
Installazione dell'SDK per i servizi App Engine
Per installare l'SDK per i servizi App Engine:
Includi l'SDK nella tua app aggiungendo la seguente riga al file
requirements.txt
:appengine-python-standard>=1.0.0
Puoi trovare l'SDK su GitHub nel
appengine-python-standard
repo 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)
Piramide
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)
Aggiungi la seguente riga al
app.yaml
file prima di eseguire il deployment dell'app:app_engine_apis: true
Per eseguire il deployment dell'app, utilizza il comando
gcloud app deploy
.
Considerazioni sulla migrazione
Tieni presenti le seguenti considerazioni se esegui la migrazione al runtime di Python 3 e la tua app utilizza servizi legacy in bundle.
Test
Per testare localmente la funzionalità dei servizi in bundle precedenti 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 per l'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 coppie [RUNTIME_ID]=[PYTHON_INTERPRETER_PATH]
. Ad esempio:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path="python27=/user/bin/python2.7,python3=/usr/bin/python3"
Compatibilità con i file pickle
I servizi condivisi, tra cui Memcache, Cloud NDB e deferred utilizzano il modulo pickle per serializzare e condividere oggetti Python. Se il tuo ambiente App Engine utilizza sia Python 2 che Python 3, cosa comune durante una migrazione, devi assicurarti che gli oggetti serializzati condivisi scritti da una versione di Python possano essere ricostruiti dall'altra. Puoi trovare indicazioni sull'implementazione della compatibilità dei file pickle tra le versioni nella 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 la tua 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 la modalità differita, imposta:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
In Python 2, gli oggetti string
contengono una sequenza di valori di byte di 8 bit. In Python
3, gli oggetti string
contengono una sequenza di caratteri Unicode. Per impostazione predefinita, Python 3
pickle traduce un string
di Python 2 in unicode interpretando il 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 l'override di questa mappatura predefinita.
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 una mappatura per ciascuno dei 256 valori possibili di ogni byte in un string
di Python 2. In questo modo si evitano errori di decodifica. Tuttavia, se il tuo string
di Python 2 contiene dati Unicode effettivi esterni all'intervallo latin1
, ad esempio i dati letti da un file, cPickle non li mapperà correttamente. Pertanto, è importante aggiornare il codice Python 2 in modo che contenga i dati Unicode con oggetti unicode
e non string
per gli oggetti che memorizzi con Pickle. La guida alla compatibilità include i dettagli sugli aggiornamenti necessari.
Il metodo descritto in precedenza per aggiornare il codice Python 2 in modo da produrre serializzazioni compatibili con Python 3 si occupa delle serializzazioni di breve durata, come quelle memorizzate in Memcache. Potresti dover aggiornare o riscrivere le serializzazioni di Python 2 di lunga durata, ad esempio quelle memorizzate in Datastore nell'ambito della migrazione. Ad esempio, la serializzazione scritta utilizzando
google.appengine.ext.ndb.model.PickleProperty
potrebbe richiedere un upgrade.
Consulta la guida sulla compatibilità per saperne di più su limitazioni e problemi meno comuni.
Framework web
webapp2
non è incluso o supportato in Python 3, pertanto qualsiasi applicazione deve essere riscritta per utilizzare qualsiasi framework compatibile con WSGI (ad esempio Flask).
Una strategia di migrazione consigliata è sostituire prima l'uso di webapp2
nella tua 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 e
esegui il deployment e il test utilizzando App Engine per Python 3.
Per esempi su 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 il tuo 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 gli handler 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: 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
L'app Python 3 deve gestire il routing degli URL (ad esempio con i decoratori Flask).
Se vuoi utilizzare più gestori script
con pattern URL diversi o se vuoi utilizzare altri attributi nei gestori, ogni gestore deve specificare script: auto
.
Puoi anche ignorare il comportamento di avvio predefinito specificando un campo entrypoint
nel file app.yaml
.
Per ulteriori informazioni su come utilizzare gestori specifici, consulta le panoramiche di Blobstore, Ritardo e Posta.
Thread safety
Si presume che le app siano sicure per i thread. Le chiamate API devono essere effettuate nel thread di richiesta. Se utilizzi un'API di servizi pacchettizzati precedente all'avvio dell'app, potrebbero verificarsi errori di sicurezza.
Per scoprire di più, consulta Errori di sicurezza durante l'utilizzo di servizi pacchettizzati precedenti per Python.
Utilizzare il recupero URL
Per utilizzare URL Fetch per Python, devi chiamare esplicitamente la libreria URL Fetch.
Se la tua 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 di destinazione può verificare l'identità dell'app chiamante. Per scoprire di più, consulta la sezione 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. L'app complementare è un'app equivalente a Python 3 in cui l'utilizzo di webapp2
è stato sostituito da Flask e sono state implementate le modifiche necessarie descritte sopra per accedere ai servizi in bundle in Python 3.
Python 2 (webapp2
)
Python 3 (Flask)
Entrambe le app sono disponibili nel repo open source per i contenuti di migrazione di App Engine in Python (esempi di codice, video, codelab), rispettivamente nelle cartelle mod0
e mod1b
.