Bermigrasi ke Python 2.7

Halaman ini membahas langkah-langkah yang diperlukan untuk mengupgrade aplikasi Python Anda ke runtime Python 2.7. Setelah mengikuti panduan ini, aplikasi Anda dapat memanfaatkan berbagai kemampuan baru runtime Python 2.7, termasuk multithreading, mesin template Jinja2, akses dan upload bytecode, serta beberapa library pihak ketiga yang disertakan.

Prasyarat dan Pertimbangan

Untuk menggunakan Python 2.7, aplikasi harus memenuhi persyaratan berikut:

  • Jika menggunakan Django, aplikasi tersebut harus menggunakan versi 1.2 atau yang lebih baru. Lihat Dokumentasi Django untuk detail upgrade.
  • Jika Anda ingin menggunakan permintaan serentak, aplikasi harus menggunakan pengendali skrip Antarmuka Gateway Server Web (WSGI), seperti yang dibahas dalam Menggunakan WSGI.

Selain memenuhi prasyarat umum ini, Anda harus menggunakan versi tertentu dari beberapa fitur App Engine dan library pihak ketiga. Pastikan Anda mengupdate versi yang Anda sertakan dan impor ke dalam aplikasi, lalu menguji aplikasi secara ekstensif setelah melakukan upgrade. Daftar berikut mengidentifikasi masalah kompatibilitas utama dan merujuk ke resource lain untuk mengatasinya:

  • Performa: Performa aplikasi dapat berubah setelah melakukan upgrade ke Python 2.7. Jika latensi respons meningkat, Anda dapat meningkatkan class frontend instance dan mengaktifkan permintaan serentak. Dengan permintaan serentak, aplikasi Anda dapat memiliki performa yang lebih cepat dengan biaya instance yang lebih rendah pada instance yang lebih besar. Untuk informasi selengkapnya, lihat Penanganan Permintaan dalam Instance.
  • Django: Anda harus menggunakan Django 1.2 atau yang lebih baru dengan Python 2.7. Untuk informasi tentang mengupgrade, lihat Catatan Rilis Django.
  • PyCrypto: Crypto.Util.randpool tidak digunakan lagi dan digantikan dengan Crypto.Random. Untuk informasi selengkapnya, lihat Petunjuk tentang RandomPool.
  • webapp: template webapp tidak digunakan lagi di Python 2.7. Sebagai gantinya, Anda dapat langsung menggunakan template Django, jinja2, atau mesin template lain pilihan Anda.
  • WebOb: Python 2.7 mendukung WebOb versi 1.1. Versi ini tidak sepenuhnya kompatibel dengan versi lama (0.9). Jika aplikasi menggunakan WebOb, Anda perlu mengujinya secara ekstensif untuk menemukan error yang diakibatkan oleh upgrade tersebut.
  • zipimport: Python 2.7 tidak mendukung zipimport, tetapi Python 2.7 dapat mengimpor secara native dari file .zip.
  • simplejson: Python 2.7 tidak mendukung simplejson, tetapi Python 2.7 menyertakan modul json library standar yang setara dan jauh lebih cepat.

Permintaan Serentak dan WSGI

Fitur Python 2.7 yang paling memengaruhi desain dan performa aplikasi Anda adalah dukungannya untuk aplikasi multi-thread yang dapat menangani permintaan serentak. Kemampuan untuk menangani permintaan serentak akan meningkatkan pemanfaatan yang dapat meningkatkan performa aplikasi Anda secara signifikan, terutama untuk aplikasi yang menggunakan class instance lebih tinggi yang mengeksploitasi beberapa core CPU.

Agar dapat mengaktifkan multithreading, aplikasi harus beralih dari pendekatan berbasis Common Gateway Interface (CGI) pada runtime Python sebelumnya ke pendekatan berbasis Antarmuka Gateway Server Web (WSGI). Hal ini karena skrip CGI, yang dirancang untuk menangani permintaan secara serial, mengandalkan variabel lingkungan untuk akses ke aliran input dan output.

Meskipun model WSGI untuk menangani permintaan memberi aplikasi lebih banyak akses langsung ke aliran data input dan output (mengaktifkan permintaan serentak), menangani beberapa permintaan secara paralel dapat menyebabkan kondisi race saat logika pengendali permintaan bergantung pada atau berinteraksi dengan data yang cakupannya lebih besar daripada lokal, seperti status aplikasi. Karena alasan ini, penting untuk membuat kode secara defensif untuk menangani kondisi race guna memastikan aplikasi WSGI baru Anda threadsafe.

Lihat Membuat Aplikasi Anda Threadsafe untuk detail selengkapnya.

Mengupdate app.yaml

Python 2.7 memerlukan elemen konfigurasi runtime khusus di header app.yaml. Perhatikan bahwa elemen threadsafe: [ true | false ] diperlukan untuk aplikasi Python 2.7. Jika true, App Engine akan mengirimkan permintaan secara serentak; jika false, App Engine akan mengirimkannya secara serial. Header app.yaml berikut memungkinkan permintaan serentak:

application: myapp
version: 1
runtime: python27
api_version: 1
threadsafe: true
...

Menggunakan WSGI

Secara opsional, runtime Python 2.7 memungkinkan Anda untuk langsung menjalankan aplikasi Antarmuka Gateway Server Web (WSGI), bukan menggunakan adaptor run_wsgi_app untuk menjalankan program sebagai skrip CGI. Untuk melakukannya, ganti pengendali CGI (misalnya myapp.py) di app.yaml dengan nama aplikasi WSGI (misalnya myapp.app).

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

Anda juga perlu memindahkan objek aplikasi WSGI ke cakupan global:

import webapp2

class MainPage(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    self.response.out.write('Hello, WebApp World!')

app = webapp2.WSGIApplication([('/', MainPage)])

""" Old code:
def main():
  run_wsgi_app(app)

if __name__ == '__main__':
  main()
"""

Anda masih dapat menentukan pengendali skrip CGI di app.yaml; namun, permintaan yang ditangani oleh skrip CGI diproses secara serial, bukan bersamaan. Selain itu, Anda tidak boleh memiliki file app.yaml yang mencampur skrip CGI dan aplikasi WSGI, serta tidak dapat menetapkan threadsafe ke true jika Anda menetapkan pengendali CGI.

Beberapa konvensi dari runtime Python sebelumnya, seperti penggunaan main() dan pemeriksaan __name__ == 'main', sekarang tidak digunakan lagi. Langkah-langkah ini membantu skrip CGI di masa lalu tetap tersimpan dalam cache, tetapi setelah Anda menjalankan aplikasi WSGI secara langsung, langkah-langkah ini tidak lagi diperlukan.

Menggunakan Direktori Root Aplikasi

Di Python 2.5, skrip CGI dijalankan dengan direktori kerja saat ini yang ditetapkan ke direktori yang berisi skrip. Hal ini telah berubah di Python 2.7. Dengan WSGI, direktori kerja saat ini di awal masa aktif pengendali permintaan adalah direktori utama aplikasi.

Tinjau kode aplikasi Anda, dan pastikan semua pengendali ditulis dengan mengharapkan direktori kerja saat ini menjadi root aplikasi.

Mengonfigurasi Library

Runtime Python 2.7 menyertakan beberapa modul pihak ketiga. Beberapa modul ini tersedia secara default; modul lainnya hanya tersedia jika dikonfigurasi. Anda dapat menentukan versi yang ingin Anda gunakan.

libraries:
- name: PIL
  version: "1.1.7"
- name: webob
  version: "1.1.1"

Anda dapat menentukan bahwa aplikasi harus menggunakan modul versi terbaru. Ini berguna jika Anda mengembangkan aplikasi yang belum memiliki pengguna: Anda tidak perlu melacak versi baru. Namun, jika aplikasi Anda aktif digunakan, berhati-hatilah: Anda mungkin terkejut karena aplikasi Anda mulai menggunakan versi library baru yang tidak kompatibel dengan versi sebelumnya. Untuk menggunakan versi terbaru:

libraries:
- name: PIL
  version: latest

Untuk daftar library yang didukung, lihat Library Pihak Ketiga.

Membuat Aplikasi Anda Threadsafe

Penanganan permintaan serentak akan sederhana jika setiap pengendali hanya berinteraksi dengan variabel dalam cakupannya. Namun, hal ini segera menjadi sulit jika satu pengendali memodifikasi resource saat pengendali yang lain membacanya. Memastikan aplikasi berperilaku seperti yang diharapkan—meskipun beberapa permintaan mungkin memanipulasi data yang sama dan saling mengganggu satu sama lain—dikenal sebagai membuat aplikasi Anda "threadsafe".

Aturan utama saat mendesain aplikasi agar menjadi threadsafe adalah membatasi penggunaan resource bersama (seperti informasi status atau variabel global) sesering mungkin. Namun, biasanya Anda tidak dapat mengabaikan sepenuhnya penggunaannya, dan di situlah mekanisme sinkronisasi seperti objek kunci berperan.

Di Python 2.7, Anda memiliki akses kelibrary threading Phyton, yang memungkinkan Anda mendeklarasikan kunci pada blok logika yang memaksa kode di dalamnya untuk dijalankan secara serial, bukan secara serentak. Pertimbangkan kode berikut:

class Configuration(ndb.Model):
  some_config_data = ndb.StringProperty()
  _config_cache = None
  _config_lock = threading.Lock()
  @classmethod
  def get_config(cls):
    with cls._config_lock:
      if not cls._config_cache:
        cls._config_cache = cls.get_by_id('config')
    return cls._config_cache

Kode ini menunjukkan pembuatan cache beberapa variabel konfigurasi global menjadi variabel yang disebut _config_cache. Di sini, penggunaan objek kunci bernama _config_lock memastikan bahwa pemeriksaan untuk _config_cache yang sudah ada akan berperilaku andal. Jika tidak, variabel ini dapat membuang waktu karena melakukan beberapa perjalanan ke Datastore untuk menetapkan variabel yang sama beberapa kali dengan data yang sama, karena semua permintaan yang bersaing menemukan bahwa _config_cache kosong.

Pikirkan dengan saksama sebelum menggunakan kunci. Kunci akan memaksa thread lain yang menjalankan metode ini untuk melakukan pemblokiran. Hal ini dapat menjadi hambatan bagi performa.

Mengupdate Aplikasi Anda ke webapp2

Catatan: jika tidak menggunakan webapp sebagai pengendali permintaan, Anda dapat melewati bagian ini.

Framework web yang disertakan dengan runtime Python 2.7 telah diupgrade dari webapp menjadi webapp2. Di antara hal lainnya, webapp2 menambahkan perutean URI dan penanganan pengecualian yang lebih baik, objek respons berfitur lengkap, dan mekanisme pengiriman yang lebih fleksibel.

Template webapp kini tidak digunakan lagi. Sebagai gantinya, Anda dapat menggunakan Jinja2, Django, atau sistem template pilihan Anda (asalkan ditulis dalam Python murni).

Di App Engine, webapp2 telah diberi alias menjadi webapp, dan webapp2 kompatibel dengan versi sebelumnya. Namun, setelah mengupgrade, Anda masih harus menguji aplikasi secara menyeluruh serta memahami sintaksis dan kemampuan baru webapp2, daripada terus mengandalkan kompatibilitas dengan versi lama.

Upgrade Anda akhirnya selesai!

Setelah mengupload aplikasi, Anda perlu mengujinya secara ekstensif untuk memastikan kompatibilitas dengan versi lama. Jika Anda mengalami masalah, lihat forum.