这个周末玩了玩Google App Engine,随手写点东西,算是学习笔记吧。不当之处,请多多指正。
作者:liigo,2009/04/26夜,大连
原创链接:http://blog.csdn.net/liigo/archive/2009/04/26/4127055.aspx
转载请注明出处:http://blog.csdn.net/liigo
一,怎么想起来玩Google App Engine了呢?
近期想写一个小程序,以便在公司的电脑和家里的电脑之间随时共享数据。但是没有现成的server和虚拟主机,数据存在哪里就成了问题。为了这个小东西去专门租一个虚拟主机吗,似乎不值得。而Google App Engine (GAE)同意用户在GOOGLE的server上免费部署WEB应用程序,自然而然的满足了我的需求。
二,什么是Google App Engine?
严格的定义去官方站点(http://code.google.com/intl/en/appengine/)找吧,我(liigo)通俗的理解为,它是一个相似虚拟主机的东西,同意你把写好的WEB应用程序(WEB站点),部署在它的server上。举个样例吧,如今网络上到处都有提供“PHP + MySQL”和“ASP + SQLServer”虚拟主机服务的吧,一般每年收费从几百元到成千上万元的都有;而Google App Engine则相当于给你免费提供“Python + Datastore”和“Java Servlet/JSP + Datastore”虚拟主机服务(Datastore是GOOGLE提供的数据库,The App Engine datastore is a schemaless object datastore, with a query engine and atomic transactions.)。我们的程序跑在GOOGLE的server上,使用GOOGLE的CPU和带宽,享受GOOGLE优秀网络架构下的安全性、灵活性、可伸缩性和负载均衡。Google App Engine为每一个程序免费提供500M存储空间,充足的CPU(每日最高46CPU-hours)和带宽(每日最高上传下载流量各10G),以及每月500万点击量,足够应付大多数项目需求(必要时还能够付费扩展);而提供等值性能的普通虚拟主机,则价格不菲。眼下Google App Engine仅仅支持Python和Java,计划中将支持其他编程语言(PHP, Ruby, Perl, ASP, ESP?)。我(liigo)个人以为,Google App Engine前途不可限量,将逐步蚕食眼下的虚拟主机(virtual hosts)市场。眼下它的劣势是,仅仅支持Python和Java,而这两者显然不是WEB开发的首选。
三,Python,还是Java?
Google App Engine眼下仅仅支持Python和Java,这是个二选一的问题。从对编程语言的了解上,我应该选Java,可是考虑到开发的高速和便捷,我终于还是选择了我不怎么熟悉(甚至一度排斥)的Python。拿Java写WEB,就象拿易语言写server一样,未必是最好的选择。
四,Google App Engine之旅
照着新手教程一步步的来,刚開始进展顺利,非常快就成功的部署了第一个程序,开心啊。
四.1 app.yaml *.py 等文件都能够即时改动即时生效,不用重新启动WEBserver,非常好。
四.2 库路径,好累啊。在接触到WebApp(以及后来的webob, cgi)时卡住了,报告“ImportError”错误,似乎是找不到对应的Python库(哈哈,我还以为仅仅有易语言会提示“无法载入支持库”呢),搜索了半天,总算通过设置系统环境变量PYTHONPATH攻克了,其值为:
D:/Python25/Lib;D:/Program Files/Google/google_appengine;D:/Program Files/Google/google_appengine/lib/webob
我以为这是Google App Engine Python SDK安装包的疏忽,没有正确的设置相关库路径,害刚開始学习的人们卡壳了半天。要说Java的classpath刚開始学习的人难以理解,Python的PYTHONPATH, sys.path也好不哪里去,还别说,EF不是照样引入了EF_LIB_PATHS嘛。说多了。
四.3 不能在类定义之前使用它。WebApp最核心的一句代码:
application = webapp.WSGIApplication([('/index', MainPage)], debug=True)
我特意试了一下,把类MainPage的定义移到这一行以下,天啊,出来满屏的错误,吓得我又改回去了。可见尽管是脚本语言,也不能随着性子来。可是我真的希望把这一行写在源文件的最前面,由于这里集中了整个程序的结构。
四.4 URL中的字母是区分大写和小写的。比如:http://localhost:8080/index 写成 .../Index 就不行了,这一点不太好,应该改正。
四.5 Python格式化文本的语法,又卡住我半天。例程里有这么一句 write("%s" % a),我想再加一个"%s",尝试了各种语法,write("%s%s" % a % b),write("%s%s", a,b) 等等,深受折磨,偏偏Google也来折磨我,不同意我搜索"python %s"keyword,后来通过搜索"python format string"才找到正确答案:write("%s%s" %(a,b))。呵呵,探索的快乐。
四.6 文本转整数,用 int() 函数。依据某个id删除一个贴子,首先得到的是id的文本形式(self.request.get('id')),要先转成整数后再去数据库查找相应的记录(db.Model.get_by_id())。对python语言不熟啊,要搜索半天才找到int()这个函数。C/C++的话,我知道用atoi();Java的话,我知道用Integer.parseInt();Delphi的话,我知道用strtoint();易语言的话,我知道用"到整数()";EF的话,我知道用"文本类.到整数()";可是python的话,我要搜索半天才干找到int()。
四.7 Google的数据库Datastore。它不是传统的关系型数据库,而是对象型数据库;它不支持标准的SQL,但有相似的GQL。在python里使用的话:要先定义一个继承自db.Model的类(MyModel),指定各成员属性,相当于定义表结构(字段及其类型)吧;查询时,通过 db.GqlQuery() 构造一个GqlQuery对象(可当作MyModel对象的集合使用,如 for ... in,GQL中"select from xxx"里的"xxx",就是MyModel类的类名称"MyModel"),或通过调用类方法MyModel.gql()返回GqlQuery对象(此时GQL中不须要"select from xxx"部分了);插入时,先实例化出一个MyModel对象,对其各成员赋值,然后调用该对象的put();改动时,对MyModel对象指定成员赋值,再调用put();删除时,调用MyModel类静态方法get_by_id()或get_by_key_name(),返回一个MyModel对象,调用该对象的delete()就可以。
四.8 Django的HTML模板。演示样例中有 {% if a %}的写法,我照猫画虎,写出来的 {% if a = b %} 被报告有语法错误,查了django模板文档才知道要写成 {% ifequal a b %},不直观啊,害我猜错了。另外,感觉这个模板系统思路有问题,HTML中充斥着{%%},一塌糊涂,既不成HTML也不成Python,生产力不高(但总比在Python代码中到处嵌HTML好一些);应该借鉴Tapestry的模板思路,对HTML有最小的侵入性,让标准的HTML编辑工具(DreamWeaver)仍然能够正常工作,否则美工MM是不喜欢參予你的项目的,她非常难跟你合作。Tapestry的模板系统,是我接触到的最好的思路正确的模板系统,将来易语言的ESP(Easy Server Pages)或许会引入相似的模板。
四.9 把输出编码设定为UTF-8,就能够非常自然地显示中文了:handler.response.headers['Content-Type'] = 'text/html; charset=utf-8'
五,学习和实践的成果
这两天的成果是:走完了新手教程的整个流程,形成网站http://liigotemp.appspot.com/;写了一个简单的小程序,形成网站http://liigoshared.appspot.com/(临时没有编辑功能)。