Pages

Saturday, 24 November 2012

如何搭建SAE Python本地开发环境

SAE是Sina推出的AppEngine,目前支持Python运行环境。和所有PAAS一样,服务器环境和本地开发环境总是有区别,如果在开发和部署阶段不断修改代码,会非常繁琐。本文讲述如何在本地和服务器共享同一代码版本,可以在本地调试,服务器直接部署。
首先,因为Python本身的动态特性和强大而简介的语法,我们实现这一目标非常容易(在此对Java开发人员表示遗憾)。假定我们确定用web.py框架,mysql数据库,memcache缓存,这3个组件SAE都支持,但和本地环境均有差异。
首先我们看web.py在本地和SAE是如何运行的:
# 本地
app = web.application(('/(.*)', 'PageHandler'), globals())
if __name__ == "__main__":
    app.run()
# SAE
app = web.application(('/(.*)', 'PageHandler'), globals()).wsgifunc()
application = sae.create_wsgi_app(app)
将两者合并,我们得到一个既可以直接在本地运行,又可以直接在SAE运行的代码:
app = web.application(('/(.*)', 'PageHandler'), globals())
if __name__ == "__main__":
    app.run()
else:
    import sae
    application = sae.create_wsgi_app(app.wsgifunc())
假定文件名是app.py,则我们可以直接运行app.py就可以本地运行,而SAE要求启动文件是index.wsgi,可以创建一个硬链接至index.wsgi就可以了(在此对Windows开发人员表示遗憾,必须复制一份文件)
MySQL一般在本地运行开发环境,而SAE的MySQL环境参数和本地不一致,但我们可以借助SAE的MySQL常量实现动态加载配置:
def _create_db():
    # 本地环境
    host = 'localhost'
    db = 'weather'
    port = 3306
    user = 'weather'
    pw = 'weather'
    try:
        import sae.const
        db = sae.const.MYSQL_DB
        user = sae.const.MYSQL_USER
        pw = sae.const.MYSQL_PASS
        host = sae.const.MYSQL_HOST
        port = int(sae.const.MYSQL_PORT)
    except ImportError:
        pass
    return web.database(dbn='mysql', host=host, port=port, db=db, user=user, pw=pw)
db = _create_db()
随后引用db变量就可以完成数据库操作。
SAE的memcached用的pylibmc,但是本地开发推荐用memcache(一个纯Python客户端),由于所有的memcached 的客户端接口都是完全一样的(Python的动态特性保证了接口一致,Java不行,必须预定义接口,各个客户端去实现),本地和远程可共享以下代码:
def _create_memcache_client():
    try:
        import pylibmc
        return pylibmc.Client()
    except ImportError:
        import memcache
        return memcache.Client(['127.0.0.1:11211'])
cache = _create_memcache_client()
充分利用Python的动态特性,以及模块的动态导入特性,我们就可以写出一份代码,本地和远程同时运行。