בדף הזה מוסבר איך להתקין ולהשתמש בשירותים מדור קודם שצורפו ל-Python 3 runtime בסביבה הרגילה. האפליקציה שלכם חייבת לגשת לשירותים הכלולים בחבילה באמצעות App Engine services SDK ל-Python 3.
לפני שמתחילים
- אפשר לעיין ברשימת ממשקי ה-API של שירותים מדור קודם בחבילה שאפשר להפעיל בסביבת זמן הריצה של Python.
- לפני שמתחילים פרויקט העברה ל-Python 3, כדאי לעיין בסקירה הכללית של העברת זמן הריצה ובשיקולים להעברה כשמשתמשים בשירותים קודמים בחבילה.
התקנה של App Engine services SDK
כדי להתקין את App Engine services SDK, פועלים לפי השלבים הבאים:
כדי לכלול את ה-SDK באפליקציה, מוסיפים את השורה הבאה לקובץ
requirements.txt:appengine-python-standard>=1.0.0ערכת ה-SDK זמינה במאגר
appengine-python-standardב-GitHub וב-PyPI.מוסיפים את הקוד הבא לסקריפט ה-Python הראשי. הקוד הזה יוצר תוכנת ביניים של WSGI שמגדירה את המשתנים שנדרשים להפעלת קריאות ה-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)פירמידה
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)מוסיפים את השורה הבאה לקובץ
app.yamlלפני פריסת האפליקציה:app_engine_apis: trueכדי לפרוס את האפליקציה, משתמשים בפקודה
gcloud app deploy.
שיקולים לגבי מיגרציה
אם אתם עוברים לסביבת זמן הריצה של Python 3 והאפליקציה שלכם משתמשת בשירותים מדור קודם, כדאי שתקראו את הנקודות הבאות.
בדיקה
כדי לבדוק באופן מקומי את הפונקציונליות של שירותים בחבילה מדור קודם באפליקציית Python 3, משתמשים בשרת פיתוח מקומי.
כשמריצים את הפקודה dev_appserver.py, צריך להגדיר את הארגומנט --runtime_python_path כך שיכלול נתיב לפרשן Python 3.
לדוגמה:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path=/usr/bin/python3
אפשר גם להגדיר את הארגומנט כרשימה מופרדת בפסיקים של זוגות [RUNTIME_ID]=[PYTHON_INTERPRETER_PATH]. לדוגמה:
python3 CLOUD_SDK_ROOT/bin/dev_appserver.py --runtime_python_path="python27=/user/bin/python2.7,python3=/usr/bin/python3"
תאימות ל-Pickle
שירותים משותפים, כולל Memcache, Cloud NDB ו-deferred, משתמשים במודול pickle כדי לבצע סריאליזציה של אובייקטים של Python ולשתף אותם. אם בסביבת App Engine שלכם נעשה שימוש גם ב-Python 2 וגם ב-Python 3, כמו שקורה בדרך כלל במהלך העברה, אתם צריכים לוודא שאפשר לשחזר אובייקטים משותפים שעברו סריאליזציה ונכתבו על ידי גרסה אחת של Python על ידי הגרסה השנייה. במדריך מפורטות הנחיות להטמעת תאימות בין גרסאות שונות של pickle.
כברירת מחדל, Python 3 משתמש בפרוטוקולי pickling שלא נתמכים ב-Python 2.
הדבר עלול לגרום לכשלים כשהאפליקציה מנסה לשחזר אובייקט Python בסביבת Python 2 שנכתבה בסביבת Python 3.
כדי למנוע את הבעיה הזו, צריך להגדיר את משתני הסביבה הבאים בקובץ app.yaml של אפליקציית Python 3 לפי הצורך:
- באפליקציות שמשתמשות ב-Memcache, כולל אפליקציות שמשתמשות ב-NDB, צריך להגדיר:
MEMCACHE_USE_CROSS_COMPATIBLE_PROTOCOL: 'True' - באפליקציות שמשתמשות ב-NDB כדי להתחבר ל-Datastore, צריך להגדיר:
NDB_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True' - באפליקציות שמשתמשות בהמרות מושהות, מגדירים:
DEFERRED_USE_CROSS_COMPATIBLE_PICKLE_PROTOCOL: 'True'
ב-Python 2, אובייקטים מסוג string מחזיקים רצף של ערכי בייטים של 8 ביט. באובייקטים של Python
3, string יש רצף של תווי Unicode. כברירת מחדל, מודול pickle של Python 3 מתרגם את string של Python 2 ל-Unicode על ידי פירוש string של Python 3 כ-ASCII. הדבר עלול לגרום לשגיאות בערכים מחוץ לטווח התווים של ASCII, 0 עד 127. Memcache תומך בביטול המיפוי הזה שמוגדר כברירת מחדל.
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))
הקידוד latin1 מגדיר מיפוי לכל אחד מ-256 הערכים האפשריים של כל בייט ב-Python 2 string. כך נמנעות שגיאות בפענוח. עם זאת, אם קובץ Python 2 string מכיל נתוני Unicode בפועל מחוץ לטווח latin1, כמו נתונים שנקראו מקובץ, המיפוי של הנתונים על ידי cPickle לא יהיה נכון. לכן, חשוב לעדכן את הקוד ב-Python 2 כך שיכיל נתוני Unicode עם אובייקטים מסוג unicode ולא אובייקטים מסוג string, עבור אובייקטים שאתם מבצעים עליהם Pickle. במדריך התאימות מפורטים העדכונים הנדרשים.
השיטה שמתוארת למעלה לעדכון קוד Python 2 כדי ליצור סדרות תואמות של Python 3 מתייחסת לסדרות לטווח קצר, כמו אלה שמאוחסנות ב-Memcache. יכול להיות שתצטרכו לעדכן או לכתוב מחדש סריאליזציות של Python 2 לטווח ארוך, כמו אלה שמאוחסנות במאגר נתונים כחלק מההעברה. לדוגמה, יכול להיות שיהיה צורך לשדרג סריאליזציה שנכתבה באמצעות google.appengine.ext.ndb.model.PickleProperty.
במדריך התאימות אפשר לקרוא מידע נוסף על מגבלות ועל בעיות פחות נפוצות.
מסגרות אינטרנט
webapp2 לא נכלל ב-Python 3 ולא נתמך בו, ולכן צריך לשכתב כל אפליקציה כדי להשתמש בכל מסגרת תואמת WSGI (כמו Flask).
אסטרטגיית המיגרציה המומלצת היא קודם להחליף את השימוש ב-webapp2 באפליקציית Python 2.7 ב-Flask (או ב-framework חלופי לאינטרנט, כמו Django, Pyramid, Bottle או web.py), ולהישאר ב-Python 2.7.
לאחר מכן, כשהאפליקציה המעודכנת יציבה, מעבירים את הקוד ל-Python 3 ופורסים ובודקים באמצעות App Engine ל-Python 3.
דוגמאות להמרת אפליקציות Python 2.7 שמשתמשות ב-webapp2 לשימוש ב-Flask framework מופיעות במקורות המידע הנוספים האלה.
שימוש באפליקציות ניהול
לאפליקציית Python 3 יכול להיות רק סקריפט אחד שמשויך אליה, לכן אם בקובץ
app.yaml יש כמה רכיבי handler של script שממפים כתובות URL לסקריפטים שונים,
תצטרכו לשלב את הסקריפטים האלה לסקריפט אחד שמטפל בניתוב כתובות ה-URL.
בדוגמה הבאה מוצגים ההבדלים בין פונקציות ה-handler בקובץ app.yaml עבור סביבות הריצה המתאימות.
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_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
אפליקציית Python 3 צריכה לטפל בניתוב כתובות URL (לדוגמה, באמצעות מעצבי Flask).
אם רוצים להשתמש בכמה רכיבי handler עם תבניות שונות של כתובות URL, או אם רוצים להשתמש במאפיינים אחרים ברכיבי ה-handler, כל רכיב handler צריך לציין את script: auto.script
אפשר גם לשנות את התנהגות ברירת המחדל של ההפעלה על ידי ציון שדה entrypoint בקובץ app.yaml.
למידע נוסף על אופן השימוש בגורמים מטפלים ספציפיים, אפשר לעיין במאמרים בנושא Blobstore, Deferred ו-Mail.
Thread safety
ההנחה היא שהאפליקציות בטוחות לשימוש עם שרשורים. קריאות ל-API צריכות להתבצע בשרשור הבקשה. אם משתמשים ב-API של שירותים בחבילה מדור קודם כשהאפליקציה מתחילה לפעול, יכולות להתרחש שגיאות אבטחה.
מידע נוסף זמין במאמר שגיאות אבטחה בשימוש בחבילות שירותים מדור קודם ל-Python.
שימוש ב-URL Fetch
כדי להשתמש ב-URL Fetch ל-Python, צריך לקרוא במפורש לספריית URL Fetch.
אם אפליקציית Python 3 שלכם משתמשת ב-URL Fetch API, כותרת הבקשה X-Appengine-Inbound-Appid מתווספת כשהאפליקציה שולחת בקשה לאפליקציית App Engine אחרת. כך אפליקציית היעד יכולה לאמת את הזהות של האפליקציה ששלחה את הבקשה. מידע נוסף זמין במאמר בנושא העברת בקשות יוצאות.
דוגמה (App Engine ndb)
למטה מופיעה אפליקציית Python 2 בסיסית שרושמת ביקורים בדף באמצעות App Engine ndb כדי לגשת ל-Datastore. האפליקציה המקבילה היא אפליקציית Python 3 שבה השימוש ב-webapp2 הוחלף ב-Flask, והשינויים הנדרשים שמתוארים למעלה כדי לגשת לשירותים בחבילה ב-Python 3 יושמו.
Python 2 (webapp2)
Python 3 (Flask)
אפשר למצוא את שתי האפליקציות האלה במאגר הקוד הפתוח של תוכן ההעברה של Python App Engine (דוגמאות קוד, סרטונים, סדנאות קוד), באופן ספציפי בתיקיות mod0 ו-mod1b.