Friday, January 26, 2024

Google App Engine - migrating from Python 2.7 to Python 3.x

Migration should be done in two phases. First, we'll switch from the webapp2 framework to Flask without upgrading the Python version. We'll check that everything is running smoothly, and then proceed switching to Python 3.x.

Before we start, we'll ensure that our existing code is intact in case we want to revert to it for some reason. So:
  1. create a separate git branch with old code

    If you are using Eclipse, right-click on the project, open the Team submenu, select Switch To, and then choose New Branch. Give the branch a name (e.g. webapp2_p27) and click on Finish. Commit and push your new branch.

    We won't be touching this code, so we can now:

  2. switch back to the main branch.

    Right-click on the project, open the Team submenu, select Switch To, and then choose main.

Migrating to Flask (Python 2.7)

  1. create a separate git branch [flask_p27]

    Use the same procedure as above, but now we are not switching back to main branch.

    In your source directory:

  2. create a static directory and move your index.html there
  3. add a simple main.py [! the link is only for my own convenience] that renders only index.html

    Example:

    from flask import Flask, send_file

    app = Flask(__name__)

    @app.route("/")
    def root():
        return send_file("static/index.html")

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


  4. add a requirements.txt [!] file containing Flask
  5. create lib directory
  6. pip install -t lib/ Flask
  7. add an appengine_config.py [!] file (if you don't have it already) with the following content:

    from google.appengine.ext import vendor
    vendor.add("lib")


  8.  update app.yaml with the following (replace existing handler):

    - url: /
      script: main.app
      secure: always

  9. run the app to make sure it works

    On Eclipse: right click on source directory, Run As, PyDev: Google App Run.

  10. you can even deploy it (better not as an default version) and make sure that everything works on production as well:

    gcloud app deploy --no-promote app.yaml

It's time to start committing to the branch and to replace handlers one by one.

It might be that the development datastore admin view will start crashing with the following error message:

raise exception('%s must not be empty.' % name)
BadArgumentError: app must not be empty.

The fix is to export this environment variable BEFORE running your dev_appserver.py.

export APPLICATION_ID=dev~None

See the following StackOverflow question. If you are using Eclipse, you can add this variable by editing Run configuration, tab Environment.

Test your app thoroughly, including both API directly plus cross-origin requests. Once tested deploy as default version and test once again from the live website. 

Merge branch to main (and leave it, do not delete it). 

In Eclipse: right click on the project select Team menu item, then Switch To, and then main. Once you switched, right click on the project again, Team, Merge, and then select flask_p27.

We are ready for the next step, and that is ...

Migrating to Python 3.x

  1. create a separate git branch [flask_p3]
  2. switch python to version 3.x (google)

    In Eclipse, right click on the project name, open Properties, PyDev - Interpreter/Gramar, change Interpreter, click on Apply and Close.

  3. edit app.yaml
    • change runtime from python27 to python38
    • remove api_version
    • add app_engine_apis: true
    • remove threadsafe

      The app can not be run through "Google App run" as before, run it from the console in python 3.x virtual environment.

  4. add appengine-python-standard and other necessary libraries to requirements.txt

    (and install them using pip install -r requirements.txt in python virtual environment).

  5. delete the file appengine_config.py and lib directory
  6. add the following to main.py

    app.wsgi_app = wrap_wsgi_app(app.wsgi_app)

  7. run python .\main.py
  8. Resolve all python errors.
  9. replace (if used) os.environ["SERVER_SOFTWARE"] with another method of detecting development environment.
  10. Test service by service.
  11. Deploy and enjoy!
  12. Yes! Once everything runs smooth, don't forget to merge that branch with the main one.

No comments:

Post a Comment