發表文章

目前顯示的是有「AppEngine」標籤的文章

OAuth in GAE

因為需要用到Google的某個service, 而那個service需要用OAuth認證, 最近研究了一下OAuth2要如何在GAE上用. 身為OAuth2推手之一的Google, 在推廣OAuth2及提供對應的Tools來說, 盡了很大的心力. 以python來說, 它就提供了 google-api-python-client 這個library, 可以很容易的使用OAuth. 我參考了這份 文件 實驗成功使用OAuth2了, 特別記錄一下. 安裝 在Linux與MacOS下十分簡單, 只要'sudo easy_install --upgrade google-api-python-client'即可安裝完成. Windows下就哭哭了, 但是最後的成果是可以在Windows下的dev_appserver.py裡執行的. 在 Google APIs Console 裡註冊你的AP 在左邊的下拉選單裡新增一個Project. 在Service那欄裡找出對應的API, 把它切換成On. 點API Access. 點Create on OAuth 2.0 client ID. 因為是GAE, 選Web application. Hostname可以先打localhost. 點Create後, 會產生三個像密碼一樣的東西, 兩個link. 把它們抄寫到一個叫settings.py的檔裡. 等等會用到. CLIENT_ID='把那串密碼裡的Client ID填在這' CLIENT_SECRET='把那串密碼裡的Client secret填在這' SCOPE='' #這是要使用的API應該會提供的資訊, 從API的文件取得. 在安裝完 google-api-python-client 後, 會在/usr/local/bin裡裝一個enable-app-engine-project的script. 如果已經有把/usr/local/bin加入PATH的話, 直接執行後面加project目錄即可. e.g. enable-app-engine-project ./ 上面那段command會複製一大堆目錄檔案過來, 把你的目錄搞的亂七八糟, 不過就將就著用吧. ...

touch data for all kinds

用AppEngine寫程式, 經常會有需要一次update所有的data, 可是如果真的要上傳一個新的version去GAE上執行很麻煩, 而且又因為GAE很容易timeout, 要把一件事分很多段來做, 或是用mapreduce. 總之是很花時間的苦差事. 而且通常這種事只要做一次, 上傳一份特別的code總是很不舒服. 後來在網路上看到了這個作法, 真是相當貼心呀. 首先要先用remote api. $ python ~/scripts/google_appengine/remote_api_shell.py -s xxxx.appspot.com 輸入帳號跟密碼後, 就會出現標準的python command line App Engine remote_api shell Python 2.7.1+ (r271:86832, Apr 11 2011, 18:13:53) [GCC 4.5.2] The db, users, urlfetch, and memcache modules are imported. xxxx> 先執行兩行 xxxx> sys.path.append(os.getcwd()) xxxx> from models import * 最後一行會把這個AP定義好的model都import進來, 如果你們沒有models.py做這件事的話, 就不要學了... :P 然後學到的重點就是可以用下面這一招 >>> len ([e.put() for e in XXXX.all().filter().fetch(1000)]) 只要有先定義好的index, filter()裡面的條件可以任意的設定. 把filter()整個拿掉也行. 這樣它會把每一個entity拿出來, 再執行一次put(). 這樣就可以達到更新model的用意, 而且顯然也不受timeout的限制, 十分好用.

Data store encoding issue

唔, 為了省空間, 想把一些放在 app engine data store 裡的文字, 用 zlib 壓縮起來放到 blob 裡. 在壓的過程中發現一些exception. 找了一些方法, 現在大致可以運作了... 原本 import zlib compressed = zlib.compress(log)  # 這行就會發生exception 現在改成 compressed = zlib.compress(log.encode('utf-8'))  # 這樣就可以了 但是在unzip的時候, 也要decode回來. zlib.decompress(compress).decode('utf-8') 這樣內容才會對喔...

Entity group

慢慢對 App engine 的 data model 有感覺了, 之前還習慣用SQL的時候, 總覺得要抓什麼都得用query, 所以在 App engine 裡也不自覺地動不動就用下面這三種方法來抓data, 即使只要抓一筆資料回來.

app engine datastore benchmark

用 app engine 最難以適應的應該就是 data store 了, 它是基於big table做出來的一種分散式的資料庫. 因為是分散式, 號稱非常scalable. 不過也因為是分散式, 很多在relational database很直覺的功能都不能用. app engine 還有每個request只能執行30秒的限制, 所以一些database更新的行為要分段做, 更增加寫程式的困難度. 寫的時候除了更小心一點, 我還想知道app engine到底寫data store有多慢. (或多快?)

用cron來觸發mapreduce job

GAE + mapreduce雖然好用, 但是老要用它那個簡單的介面來觸發一個job. 不能自動化的每天自動起來做些統計的事, 感覺挺蠢的. 一直在找要怎麼加, 才能在cron.yaml裡觸發. 終於被我試出來了. 首先, 先指定一個url給特定的handler. 最簡單就是在app.yaml把所有link都導到main.py. app.yaml - url: .*   script: main.py 然後在main.py裡加一段 def main():     application = webapp.WSGIApplication(...         ('/tasks/summary', SummaryHandler)],         debug=True)     util.run_wsgi_app(application) 重點就是這個SummaryHandler. class SummaryHandler(webapp.RequestHandler):     def get(self):         name = 'count'         handler_spec = 'main.process'         reader_spec = 'mapreduce.input_readers.DatastoreInputReader'         reader_parameters = {'entity_kind': 'main.Client'}         start_map(name, handler_spec, reader_spec, reader_parameters) 當然啦, 前面要from mapreduce.con...

一定要自己踢過一次鐵板才能學會 (二)

圖片
經過一夜的蒐集資料, 看了 Google I/O 的影片, 覺得用 MapReduce 就是正解啦. 用法很簡單 Step 1 Download最新的 MapReduce , 在local自己的appengine程式的地方執行. svn checkout http : //appengine-mapreduce.googlecode.com/svn/trunk/python/src/mapreduce Step 2 修改app.yaml, 固定都是加上下列這段code. - url: /mapreduce(/.*)? script: mapreduce/main.py login: admin Step 3 新增一個mapreduce.yaml檔 mapreduce: - name: Count the number of entities mapper: input_reader: mapreduce.input_readers.DatastoreInputReader handler: jobs.process params: - name: entity_kind default: main.Report 第一個name, 就是之後會顯示在mapreduce的網頁介面上的job name. input_reader, 目前有四種reader可以選, 詳情可見 這裡 . 主要是從DataStore裡抓, 或是從BlobStore裡抓, 或是從zip檔裡抓資料. handler, 指定之後會被MapReduce call的function. 這裡有點tricky, 文件寫得不是很清楚, 查了MapReduce的source才知道要填什麼. 簡單的說它可以吃三四種格式, 會試著用不同的方法去找到對應的python檔, class定義跟function定義. 最簡單的方法就是"file.function". 像這裡就是有一個叫jobs.py的檔, 裡面有一個process(). 之後MapReduce就會一直重覆地呼叫這個function. param, 這裡可以指定一些參數, 最重要的是entity_kind這個欄位, 這裡指定了預設值是main.py裡定義的R...

一定要自己踢過一次鐵板才能學會 (一)

在公司的一個appengine程式, 終於蒐集了一小筆資料(不到一千筆), 現在想對這些資料做些統計, 再用Google Chart API顯示出來. 可以預期等到這個程式正式上線, 資料是幾十幾百萬來計算的時候, 這個統計方法一定會有問題, 不過我還沒什麼想法, 現在一開始是這麼做的.