יחידת לימוד 2: מעבר מ-App Engine ndb ל-Cloud NDB

1. סקירה כללית

סדרת המדריכים הזו (מדריכים מעשיים בקצב אישי) נועדה לעזור למפתחים של Google App Engine (רגיל) לחדש את האפליקציות שלהם על ידי הדרכתם לאורך סדרה של העברות. השלב המשמעותי ביותר הוא הפסקת השירותים המקוריים בחבילה עם סביבת זמן ריצה, כי זמני הריצה של הדור הבא גמישים יותר ומספקים למשתמשים מגוון רחב יותר של אפשרויות שירות. המעבר לסביבת זמן הריצה מהדור החדש יותר מאפשר לכם להשתלב בקלות עם מוצרי Google Cloud, להשתמש במגוון רחב יותר של שירותים נתמכים ולתמוך בגרסאות בשפות הקיימות.

במדריך הזה תלמדו איך לעבור מספריית הלקוח המובנית של ndb (מסד הנתונים הבא) אל ספריית הלקוח של Cloud NDB.

כאן מוסבר איך

  • שימוש בספרייה ndb של App Engine (אם אינך מכיר אותה)
  • העברה מ-ndb ל-Cloud NDB
  • העברה נוספת של האפליקציה ל-Python 3

מה צריך להכין

סקר

איך בכוונתך להשתמש ב-Codelab הזה?

לקריאה בלבד לקרוא אותו ולבצע את התרגילים

2. רקע

במודול 1, העברנו frameworks של אינטרנט מה-webapp2 המובנה של App Engine ל-Flask. ב-Codelab הזה, אנחנו ממשיכים להפסיק את השירותים המובְנים של App Engine על ידי מעבר מספריית ndb של App Engine אל Google Cloud NDB.

בסיום ההעברה, תוכלו:

  1. עוברים ל-Python 3 ודור הריצה של App Engine מהדור הבא
  2. העברה ל-Cloud Datastore (ספריית לקוח לאפליקציות שאינן של App Engine)
  3. יוצרים קונטיינרים לאפליקציית Python 2 (או 3) ועוברים ל-Cloud Run
  4. הוספת שימוש בתורי המשימות של App Engine (push) ולאחר מכן מעבר ל-Cloud Tasks

אבל עוד לא הגענו. כדאי לסיים את ה-Codelab הזה לפני שבוחנים את השלבים הבאים. ההעברה של המדריך הזה כוללת את השלבים העיקריים הבאים:

  1. הגדרה/עבודה מוקדמת
  2. הוספה של ספריית Cloud NDB
  3. עדכון קובצי אפליקציה

3. הגדרה/עבודה מוקדמת

לפני שנתחיל בחלק המרכזי של המדריך, כדאי להגדיר את הפרויקט, לקבל את הקוד ואז לפרוס את אפליקציית הבסיס כדי שנדע שהתחלנו לעבוד עם קוד.

1. הגדרת הפרויקט

אם השלמתם את Codelab של Module 1, מומלץ להשתמש שוב באותו פרויקט (ובקוד). לחלופין, אפשר ליצור פרויקט חדש לגמרי או להשתמש שוב בפרויקט קיים. צריך לוודא שלפרויקט יש חשבון פעיל לחיוב וש-App Engine מופעל.

2. אחזור של אפליקציה בסיסית לדוגמה

אחת הדרישות המוקדמות היא שתהיה לכם אפליקציה לדוגמה של מודול 1 פעיל. אם סיימתם את המדריך, השתמשו בפתרון הרלוונטי. אפשר להשלים את התהליך עכשיו (בקישור שלמעלה). אם רוצים לדלג עליו, אפשר להעתיק את המאגר של מודול 1 (קישור למטה).

בין אם אתם משתמשים בקוד של יחידת הלימוד שלכם או שלנו, קוד המודול 1 הוא המקום שבו נתחיל. ה-Codelab במודול 2 הזה ינחה אותך לאורך כל שלב, ובסיום התהליך הוא אמור להיראות כמו קוד בנקודה FINISH (כולל יציאת 'בונוס' אופציונלית מ-Python 2 עד 3):

תיקיית הקוד STARTing Module 1 צריכה להכיל את התוכן הבא:

$ ls
README.md               appengine_config.py     requirements.txt
app.yaml                main.py                 templates

אם השלמתם את המדריך של מודול 1, תהיה לכם גם תיקייה lib עם Flask ותלויי התלות שלה. אם אין לך תיקיית lib, צריך ליצור אותה באמצעות הפקודה pip install -t lib -r requirements.txt כדי שנוכל לפרוס את אפליקציית הבסיס הזו בשלב הבא. אם גם Python 2 וגם 3 מותקנים, אנחנו ממליצים להשתמש ב-pip2 במקום ב-pip כדי למנוע בלבול עם Python 3.

3. (מחדש) פריסה של אפליקציית מודול 1

שאר השלבים לפני העבודה שצריך לבצע עכשיו:

  1. כדאי להכיר מחדש את כלי שורת הפקודה gcloud (אם רלוונטי)
  2. (אם צריך לפרוס מחדש את הקוד של מודול 1 ב-App Engine)

אחרי שתבצעו את השלבים האלה ותוודאו שהוא פועל, נתקדם במדריך הזה ונתחיל מקובצי התצורה.

4. עדכון קובצי התצורה (הוספת ספריית Cloud NDB)

שירותים מובנים רבים ומקוריים של App Engine התבלטו במוצרים שלהם, ו-Datastore הוא אחד מהם. כיום אפליקציות שאינן של App Engine יכולות להשתמש ב-Cloud Datastore. עבור משתמשי ndb ותיקים, צוות Google Cloud יצר את ספריית הלקוח Cloud NDB כדי לדבר עם Cloud Datastore. היא זמינה גם ב-Python בגרסה 2 וגם בגרסה 3.

אנחנו נעדכן את קובצי האישור כדי להחליף את App Engine ndb ב-Cloud NDB ואז נשנה את האפליקציה שלנו.

1. עדכון של requirements.txt

במודול 1, התלות החיצונית היחידה של האפליקציה שלנו הייתה Flask. עכשיו נוסיף את Cloud NDB. כך נראה קובץ requirements.txt בסוף יחידת לימוד 1:

  • לפני:
Flask==1.1.2

מעבר מ-App Engine ndb מחייב ספריית Cloud NDB (google-cloud-ndb), ולכן צריך להוסיף את החבילה אל requirements.txt.

  • אחרי:
Flask==1.1.2
google-cloud-ndb==1.7.1

כשכותבים את ה-Codelab הזה, הגרסה המומלצת האחרונה היא 1.7.1, אבל יכול להיות שהגרסה של requirements.txt במאגר היא חדשה יותר. אנחנו ממליצים על הגרסאות העדכניות של כל ספרייה, אבל אם הן לא פועלות, אפשר לחזור לגרסה ישנה יותר.

מוחקים את lib אם יש תיקייה כזו ולא רק יצרתם אותה למעלה. עכשיו (מתקינים מחדש את הספריות המעודכנות באמצעות הפקודה pip install -t lib -r requirements.txt, תוך שימוש ב-pip2 במקום ב-pip לפי הצורך).

2. עדכון של app.yaml

כדי להוסיף ספריות לקוח של Google Cloud, כמו google-cloud-ndb, יש כמה דרישות, סביב הוספת ספריות לקוח "מובְנות". ספריות, חבילות של צד שלישי שכבר זמינות בשרתי Google. הם לא רשומים ב-requirements.txt וגם לא מעתיקים אותם עם pip install. הדרישות היחידות:

  1. הגדרת ספריות מובנות ב-app.yaml
  2. להפנות אותם לספריות של צד שלישי שהועתקו שהם עשויים לעבוד איתן (ב-lib)

הנה app.yaml 'התחלה' ממודול 1:

  • לפני:
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

עכשיו מוסיפים את השורות הבאות אל app.yaml כדי להפנות לחבילות של חבילות צד שלישי: grpcio ו-setuptools בקטע libraries חדש:

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

למה כדאי להשתמש בספריות המובנות האלו? gRPC היא מסגרת RPC פתוחה שמשמשת את כל ספריות הלקוח של Google Cloud, כולל google-cloud-ndb. הספרייה grpcio היא מתאם gRPC ב-Python, ולכן היא נדרשת. בקרוב נוסיף את הסיבה להכללה של setuptools.

  • אחרי:

לאחר השינויים שלמעלה, app.yaml המעודכן שלך אמור להיראות כך:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

3. עדכון של appengine_config.py

הכלי pkg_resources, חלק מהספרייה setuptools, מאפשר לספריות מובנות של צד שלישי לגשת לספריות המובנות של צד שלישי. יש לעדכן את appengine_config.py כדי להשתמש ב-pkg_resources שיפנה אותם לספריות המקובצות ב-lib. לאחר השלמת השינוי הזה, הקובץ כולו אמור להיראות כך:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

5. עדכון קובצי אפליקציה

הרשמיות של קובץ התצורה מפריעות, ועכשיו אפשר לעבור מ-ndb ל-Cloud NDB. כדי להשלים את ההעברה, צריך לעדכן את הספריות המיובאות ולהוסיף שימוש בניהול הקשר ב-main.py.

1. יבוא

ביצוע החלפת הייבוא הבאה ב-main.py:

  • לפני
from google.appengine.ext import ndb
  • אחרי:
from google.cloud import ndb

לפעמים, המעבר מספריית App Engine לספרייה ב-Google Cloud הוא פשוט כמו במופע הזה. לשירותים מובנים שהפכו למוצרים מלאים של Google Cloud, הייבוא ייובא מ-google.cloud במקום מ-google.appengine.

2. גישה ל-Datastore

כדי להשתמש בספריית Cloud NDB, צריך להשתמש במנהלי הקשר של Python באפליקציה. מטרתן היא "לשער" גישה למשאבים כך שיהיה צורך לרכוש אותם לפני שאפשר להשתמש בהם. מנהלי הקשר מבוססים על השיטה לבקרה במדעי המחשב שנקראת הקצאת משאבים Is Initialization (או RAII). מנהלי הקשר משתמשים עם קובצי Python (שצריך לפתוח כדי לגשת אליהם) ועם בו-זמניות, "נעילות מסתובבות" לפני קוד ב"קטע קריטי", ניתן לביצוע.

באופן דומה, כדי להפעיל פקודות של Datastore ב-Cloud NDB צריך לקבל את ההקשר של הלקוח שישמש לתקשורת עם Datastore. קודם כול, יוצרים לקוח (ndb.Client()) על ידי הוספה של ds_client = ndb.Client() ב-main.py מיד אחרי אתחול Flask:

app = Flask(__name__)
ds_client = ndb.Client()

הפקודה ב-Pythonwith משמשת אך ורק לקבלת ההקשר של האובייקט. צריך לשלב בלוקים של קוד לגישה ל-Datastore באמצעות דפי חשבון with.

בהמשך מוצגות אותן הפונקציות ממודול 1 לכתיבת ישות חדשה ב-Datastore וקריאה להצגת הישויות האחרונות שנוספו:

  • לפני:

הנה הקוד המקורי ללא ניהול הקשר:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return (v.to_dict() for v in Visit.query().order(
            -Visit.timestamp).fetch(limit))
  • אחרי:

עכשיו מוסיפים את with ds_client.context(): ומעבירים את קוד הגישה של Datastore לבלוק with:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return (v.to_dict() for v in Visit.query().order(
                -Visit.timestamp).fetch(limit))

אפליקציית מנהל ההתקן הראשית נשארת זהה לזו שהייתה לנו ממודול 1, כי אין כאן קוד ndb (או Cloud NDB):

@app.route('/')
def root():
    'main application (GET) handler'
    store_visit(request.remote_addr, request.user_agent)
    visits = fetch_visits(10)
    return render_template('index.html', visits=visits)

שיטה מומלצת היא ליצור הבחנה ברורה בין קוד האפליקציה לבין הגישה לנתונים. כך הקוד הראשי של האפליקציה לא ישתנה כשהמערכת תחיל את השינוי במנגנון מאגר הנתונים הבסיסי, כפי שביצענו בהעברה הזו.

6. סיכום/ניקוי

פריסת אפליקציה

פורסים מחדש את האפליקציה באמצעות gcloud app deploy ומוודאים שהאפליקציה פועלת. הקוד אמור עכשיו להתאים למה שמופיע במאגר של מודול 2.

אם עברתם לסדרה הזו בלי לבצע אף אחת מההדרכות הקודמות של הקוד, האפליקציה עצמה לא משתנה. הוא רושם את כל הביקורים בדף האינטרנט הראשי (/) ונראה כך לאחר שביקרת באתר מספיק פעמים:

אפליקציית visitme

מזל טוב, השלמת את שיעור ה-Codelab של יחידת הלימוד הזו. עברת את קו הסיום כי זו הפעם האחרונה מבין ההעברות המומלצות ביותר בסדרה הזו עד ל-Datastore.

אופציונלי: הסרת המשאבים

מה לעשות כדי שלא נחייב אתכם עד שתהיו מוכנים לעבור ל-Codelab הבא של ההעברה? כמפתחים קיימים, סביר להניח שאתם כבר מעודכנים לגבי נתוני התמחור של App Engine.

אופציונלי: השבתת האפליקציה

אם אתם עדיין לא מוכנים לעבור למדריך הבא, כדאי להשבית את האפליקציה כדי לא לצבור חיובים. כשתהיו מוכנים לעבור ל-Codelab הבא, תוכלו להפעיל אותו מחדש. בזמן שהאפליקציה מושבתת, תנועת הגולשים לא תצברו חיובים. עם זאת, חיוב נוסף הוא השימוש שלכם במאגר הנתונים אם הוא חורג מהמכסה בחינם. לכן כדאי למחוק מספיק נתונים כדי לא לחרוג מהמגבלה הזו.

מצד שני, אם אתם לא מתכוונים להמשיך בהעברות ואתם רוצים למחוק הכול לגמרי, תוכלו להשבית את הפרויקט.

השלבים הבאים

כאן יש גמישות לגבי הצעד הבא שלך. תוכלו לבחור אחת מהאפשרויות הבאות:

  • בונוס של מודול 2: המשיכו לחלק הבונוס של המדריך הזה כדי ללמוד על העברה ל-Python 3 ולדור הבא של סביבת זמן הריצה של App Engine.
  • מודול 7: תורים של משימות דחיפה ב-App Engine (נדרש אם משתמשים ב[push] תורי משימות)
    • הוספת משימות דחיפה ל-App Engine taskqueue לאפליקציית מודול 1
    • הכנת המשתמשים למעבר אל Cloud Tasks במודול 8
  • מודול 4: מעבר ל-Cloud Run באמצעות Docker
    • יצירת קונטיינרים לאפליקציה להרצה ב-Cloud Run באמצעות Docker
    • מאפשרת להמשיך להשתמש ב-Python 2
  • מודול 5: מעבר ל-Cloud Run עם Cloud Buildpacks
    • יצירת קונטיינרים לאפליקציה כדי לרוץ ב-Cloud Run באמצעות Cloud Buildpacks
    • לא צריך לדעת שום דבר על Docker, על קונטיינרים או על Dockerfile
    • צריך להעביר כבר את האפליקציה ל-Python 3
  • מודול 3:
    • מודרניזציה של הגישה ל-Datastore מ-Cloud NDB ל-Cloud Datastore
    • הספרייה הזו משמשת לאפליקציות של Python 3 App Engine ולאפליקציות שאינן של App Engine.

7. בונוס: מעבר ל-Python 3

כדי לקבל גישה לתכונות ולזמן הריצה העדכניים ביותר של App Engine, מומלץ לעבור ל-Python 3. באפליקציה לדוגמה שלנו, Datastore היה השירות המובנה היחיד שבו השתמשנו, ומאז שעברנו מ-ndb ל-Cloud NDB, עכשיו אנחנו יכולים לנייד את סביבת זמן הריצה של Python 3 ב-App Engine.

סקירה כללית

למרות שניוד ל-Python 3 לא נכלל במדריך של Google Cloud, החלק הזה ב-Codelab נותן למפתחים מושג לגבי ההבדלים בזמן הריצה של Python 3 App Engine. אחת התכונות הבולטות של סביבת זמן הריצה מהדור הבא היא גישה פשוטה יותר לחבילות של צד שלישי. לא צריך לציין חבילות מובנות ב-app.yaml ולא חובה להעתיק או להעלות ספריות לא מובנות. שהם מותקנים במרומז מרישום ב-requirements.txt.

מכיוון שהדוגמה שלנו כל כך בסיסית וגם Cloud NDB תואם ל-Python 2-3, לא צריך להעביר קוד אפליקציה באופן מפורש ל- 3.x; האפליקציה פועלת ב-2.x וב-3.x ללא שינוי, כלומר השינויים הנדרשים היחידים הם בהגדרות במקרה הזה:

  1. צריך לפשט את app.yaml כדי להפנות ל-Python 3 ולהסיר ספריות של צד שלישי.
  2. מוחקים את appengine_config.py ואת התיקייה lib כי אין בהם יותר צורך.

בנוסף לקובץ main.py, הקבצים requirements.txt ו-templates/index.html לא השתנו.

מפשטים את app.yaml

לפני:

השינוי האמיתי היחיד באפליקציה הזו לדוגמה הוא לקצר משמעותית את app.yaml. כתזכורת, זה מה שעשינו בapp.yaml בסיכום יחידת לימוד 2:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

אחרי:

ב-Python 3, כל ההוראות threadsafe, api_version ו-libraries הוצאו משימוש. כל האפליקציות נחשבות ל-threadsafe ולא נעשה שימוש ב-api_version ב-Python 3. כבר אין חבילות מובנות של צד שלישי המותקנות מראש בשירותי App Engine, ולכן גם libraries הוצא משימוש. מידע נוסף על השינויים האלה זמין במסמכי התיעוד בנושא שינויים ב-app.yaml. לכן, צריך למחוק את כל השלושה מ-app.yaml ולעדכן לגרסת Python 3 נתמכת (ראו בהמשך).

אופציונלי: שימוש בהוראה handlers

בנוסף, הוצאה משימוש גם ההוראה handlers שמפנה את תעבורת הנתונים לאפליקציות של App Engine. הדור הבא של סביבת זמן הריצה, מצפה שמסגרות אינטרנט ינהלו את ניתוב האפליקציות, ולכן כל 'הסקריפטים של ה-handler' ל-"auto". אם משלבים את השינויים שכאן למעלה, מתקבל app.yaml:

runtime: python38

handlers:
- url: /.*
  script: auto

מידע נוסף על script: auto זמין בדף המסמכים שלו.

מתבצעת הסרה של ההוראה handlers

מכיוון שהכלי handlers הוצא משימוש, אפשר גם להסיר את הקטע כולו ולהשאיר app.yaml של שורה אחת:

runtime: python38

כברירת מחדל, הפעולה הזו תפעיל את שרת האינטרנט Gunicorn WSGI, שזמין לכל האפליקציות. אם אתם מכירים את gunicorn, זו הפקודה שתבוצע כאשר היא מופעלת כברירת מחדל עם ה-ברים app.yaml:

gunicorn main:app --workers 2 -c /config/gunicorn.py

אופציונלי: שימוש בהוראה entrypoint

עם זאת, אם באפליקציה שלכם נדרשת פקודת הפעלה ספציפית, שניתן לציין אותה באמצעות הוראת entrypoint שבה ה-app.yaml ייראה כך:

runtime: python38
entrypoint: python main.py

בדוגמה הזו בקשה ספציפית להשתמש בשרת הפיתוח של Flask במקום ב-gunicorn. בנוסף, יש להוסיף לאפליקציה את הקוד שמפעיל את שרת הפיתוח כדי להפעיל אותו בממשק 0.0.0.0 ביציאה 8080. לשם כך, צריך להוסיף את הקטע הקטן הבא לתחתית של main.py:

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

מידע נוסף על entrypoint זמין בדף המסמכים שלו. דוגמאות ושיטות מומלצות נוספות מופיעות במסמכי ההפעלה הסטנדרטיים של App Engine וכן במסמכי ההפעלה הגמישה של App Engine.

מחיקה של appengine_config.py ושל lib

מוחקים את הקובץ appengine_config.py ואת התיקייה lib. במסגרת ההעברה ל-Python 3, App Engine רוכש ומתקין חבילות שמפורטות ב-requirements.txt.

קובץ התצורה appengine_config.py משמש לזיהוי ספריות/חבילות של צד שלישי, גם אם העתקתם אותן בעצמכם וגם אם אתם משתמשים בספריות שכבר זמינות בשרתי App Engine (מובְנים). לגבי Python 3, סיכום של השינויים העיקריים הוא:

  1. אין קיבוץ של ספריות של צד שלישי שהועתקו (רשומות ב-requirements.txt)
  2. לא pip install בתוך תיקייה מסוג lib, כלומר אין תקופה של lib תיקייה
  3. אין רישום של ספריות מובְנות של צד שלישי ב-app.yaml
  4. אין צורך להפנות לאפליקציה לספריות של צד שלישי, לכן אין צורך בקובץ appengine_config.py

אם צריך, מפרסמים את כל הספריות הנדרשות של צד שלישי ב-requirements.txt.

פריסת אפליקציה

צריך לפרוס מחדש את האפליקציה כדי לוודא שהיא פועלת. אפשר גם לבדוק עד כמה הפתרון שלכם קרוב לקוד Python 3 לדוגמה של מודול 2. כדי להמחיש את ההבדלים לעומת Python 2, משווים בין הקוד לגרסת Python 2 שלו.

מזל טוב, סיימת את שלב הבונוס במודול 2! למסמכי העזרה בנושא הכנת קובצי תצורה לסביבת זמן הריצה של Python 3 לסיום, יש לעיין בדף 'סיכום'/'ניקוי' (המוקדם יותר) כדי לראות את השלבים הבאים ואת הניקוי.

הבקשה שלך בהכנה.

כשמגיע הזמן להעביר את האפליקציה שלכם, תצטרכו לנייד את הקובץ main.py וקובצי אפליקציות אחרים ל- 3.x, כך ששיטה מומלצת היא להגדיר את האפליקציה מסוג 2.x כ'תואם להעברה'. ככל האפשר.

יש המון מקורות מידע באינטרנט שיכולים לעזור לכם לעשות זאת, אבל ריכזנו כאן כמה טיפים חשובים:

  1. מוודאים שכל יחסי התלות של אפליקציות תואמים באופן מלא ל- 3.x
  2. מוודאים שהאפליקציה פועלת בגרסה 2.6 לפחות (עדיף 2.7)
  3. חשוב לוודא שהאפליקציה עוברת את כל חבילת הבדיקות (וכיסוי מינימלי של 80%)
  4. שימוש בספריות תאימות כמו six, Future ו/או Modernize
  5. הסברים לגבי ההבדלים בין מפתחות 2.x ל-3.x שאינם תואמים לאחור
  6. כל קלט/פלט (I/O) יוביל ככל הנראה לאי-תאימות במחרוזות של Unicode לעומת בייטים

האפליקציה לדוגמה תוכננה מתוך מחשבה על כל זה, ולכן היא פועלת ב-2.x וב-3.x ישירות מהאריזה, כדי שנוכל להתמקד בלהראות לך מה צריך לשנות כדי להשתמש בפלטפורמה של הדור הבא.

8. מקורות מידע נוספים

בעיות/משוב על Codelabs עם מודול ההעברה של App Engine

אם נתקלתם בבעיות ב-Codelab הזה, צריך קודם לחפש את הבעיה לפני השליחה. קישורים לחיפוש וליצירת בעיות חדשות:

משאבים להעברה

בטבלה למטה מופיעים הקישורים לתיקיות המאגר של מודול 1 (START) ומודול 2 (FINISH). אפשר לגשת אליהן גם דרך המאגר לכל העברות Codelab ב-App Engine, שאותו ניתן לשכפל או להוריד בקובץ ZIP.

Codelab

ֶPython 2

ֶPython 3

יחידת לימוד 1

קוד

(לא רלוונטי)

יחידת לימוד 2

קוד

קוד

משאבי App Engine

בהמשך מופיעים מקורות מידע נוספים בנוגע להעברה הספציפית הזו: