折腾了两天发现后来发现没有用的东西,还是比较郁闷的事情。不过还好,没有被打击,又开了个新的东西。有了前面的一个经验,还是满快的,嗯。 做了一个十分简单的blog系统,说说里面有用的东西吧,由于blog很简单,所以只用了两张表,一张放文章,一张放Tags。其实本来懒到只想用一张表的,但是想想只有文章,那和留言板也没什么区别了,所以,加了个tag。文章中的taglist是用ListProperty建的,list的类型本来想用db.Key,但是查询那段代码写着太麻烦了,所以最后用了简单的字符串,没办法,我比较懒,呵呵。 还用到的一个模块就是认证,也是很简单的,传到服务器上后直接用google帐户的认证,满不错的,也满方便的,于是我就直接用了。在get时判断是否登录,如果登录了就显示表单,否则给个要登录的链接。两个用的是一个页面,用到了模板中的判断{% if %},也很方便。从表单取数据直接用self.request.get(<name>)就行了,没啥好说的。 还有个地方就是URL的正则匹配,在app.yaml中有,在webapp的main()函数中也有,我是在app.yaml中把所有的URL映射到了一个地址下,然后在webapp中细分。它的正则匹配就是在函数中按顺序匹配()中的内容,变量名随便起,然后可以直接在函数中用。 别的,没有啥了,嗯。
本来测试已经没啥问题了,但是,居然,它的那个urlfetch居然功能不全,或者是说那几个提供feed的网站有点啥,不管怎么样,结果就是,我用它的urlfet ch.fetch()抓不到我想到的数据,真郁闷。话说,更郁闷的是昨天拿来试这个功能的那个地址可以,要是昨天那个就不行了,我就不做了撒,诶。看来又要想东西做了 ,还是看看它和G家自己的东西能不能很好的结合吧……
希望这两天的时间没有白费……
灌水灌上瘾了,没办法,呵呵,就再来一篇吧。
写的那个RSS聚合应用,想在后台运行一个单独的线程,用以从那些地址更新RSS信息,一开始很傻很天真的用thread来写,写了一半想起来了,去查查支持不支持。 去开发者论坛上一找background,还真有人在讨论。扫了一眼,就是现在还不支持,然后一帮人在Google Code的某个Issue上灌水,话说我也去加了一瓢,嘿嘿。
目前不支持,但我还是要用啊,继续转,果然找到了个折衷的方法,其实也很简单,就是把那个本来要写成thread的类映射到某个URL上,然后过一段时间访问一下,这 个可以在别的任何机器上用计划任务实现。刚试了一下,效果不错,暂时先这么用着吧,呵呵。
下午做RSS聚合网站时,需要从外部的地址抓feed,用的是feedparse的库。但是怎么弄都出错,所以很郁闷,想从RSS的字符串解析一次,看看有没有错。想 当然的使用了urllib,结果它也出错。由于有了昨天模板的经验,所以直接去找google的文档。果不其然,它不支持直接从外网获取内容,如果有此需求,则需要使 用它封装好的一个urlfetch库中的fecth方法。没办法啊,那就用吧,谁让人家的地盘人家做主呢。
抓取内容,判定返回值是否为200,取结果,到这一切顺利,于是就开始用feedparse解析。解析也没问题,但是郁闷的是,这样解析出来的东西没有时间信息了,就 是它得不到这个RSS的最后更新时间,去urlfetch的文档里面转了一圈,也没见有相关的内容,只好自己另想办法了。最后的解决办法是在FeedInfo中加入了 一个字段用以存放最后更新的时间,然后拿feed中的每个文章的updated_parse时间与这个时间比较,如果文章的时间较新则插入库中,否则不处理。在写时候 漏掉一条语句,调了好长时间,真郁闷。
PS:logging真的很好用,直接在服务器的终端窗口输出信息。其实我本来是想用printf的,结果伊居然不支持,FT。
PS2:如果loggin的消息调成debug,则在开服务器的时候需要加上- d选项,否则DEBUG的信息不输出,我为这折腾了10分钟,那几条logging语句一会加上一会删除,心里还直嘀咕,难道又被我找到个BUG…….
下午想了好久,才想到做一个类似Planet的Blog聚合的东西,也算是给自己玩玩吧。看了一下文档,它不支持往主机中写文件,如果需要存放数据的话,需要使用它的 Datastore,其实就是后台给提供个数据库,这样也好,也算方便管理吧。
动手写了写,大概需要两张表,一张表维护feed的信息,另一张表存放文章的信息,反正目前是这样的,以后有什么再加吧,呵呵。和Django中类似,直接用一个cl ass表示一张表,而且也是分多种字段值,无外乎就是那些啥个文本啊,数字啊,链接啥的,与Django不同的是它需要根据字段值的不同构建一个db下某个模块的实例 。还有一个reference字段类型用来表示关联表,它存放的另一张表中的某个字段值的key。大概是因为还算比较熟悉Django的数据库模块,所以没感觉到有啥 困难。有DB就需要有查询,App Engine的查询使用的是像Django中的模块,或者使用GQL语言,和SQL类似,不过它的文档中只有SELECT,而没有 其它的诸如INSERT,UPDATE啥,不过如果需要更改数据的值可以先查询,然后直接对结果进行赋值操作后调用put操作即可。用起来还是满简单的,呵呵,反正大 概能满足我的要求了。
是支持模板了,但是居然只支持把模板放在工程的根目录,好像是权限的原因。郁闷啊,想好的目录结构就这样被破坏了,还好支持把css等静态文件扔在别的文件夹。明天折 腾折腾UI吧,困了,睡觉。
看到App Engine支持模板,扫了一眼,和Django的就是一样的,它下面的链接也直接说了,用的就是Django的模板系统。看来这次又有便宜可占了,直接 上手,不错不错。
和Django中一样,需要使用静态文件,但是在yaml文件中设置了static_dir再起服务器死活就是开不起来,直接去google.com找未果,然后想到 了它的开发group,果然碰到一群和我碰到同样问题的人。后来好像说原因是因为Windowz下用的是 \ 作为路径分隔符,在某个正则中变了转义,所以就那个啥了 。一种解决方法是在yaml文件中把所有的静态文件写进去,看着头就大;还好有人想到了用正则,于是就有了一种新的方法。
- url: /stylesheets/(.*) static_files: stylesheets/\1 upload: stylesheets/(.*) 查了一下,upload参数的意思没看太明白,好像是说如果文件匹配此参数后面的正则,就被这个handler接管,主要用处是确定和url和static_file s后面正则匹配的路径对应于哪个文件。汗自己的英语理解力,反正先用上了,确定能用了。然后按教程中写的,直接渲染吧。
居然发现了一个bug,呵呵,有意思。
在邮件列表中看到了这个东西,感觉满好玩的,是用python的,也满合胃口的,申请了一下,然后过了一会拿到的许可。有人说是在后台有一个sleep 3000,呵呵,不知道是真的假的。反正我是有了,用着玩玩吧。
下载了SDK,没细看里面的目录结构,只是知道里面有一个脚本可以当作开发时的服务器,还有一个脚本可以用以把文件上传。网站上有一个教程,老例子,上来先是一个he lloworld。它的工程中需要有一个app.yaml用以标识工程的ID,刚写的那个yaml文件如下:
application: sonic version: 1 runtime: python api_version: 1 handlers: - url: /.* script: helloworld.py version是工程的版本,runtime version和api_version这俩目前只有一种选择,不知道以后会不会更改。然后就是写主要的部分了,han dlers。首先是以减号开始,后跟url关键字,冒号后是正则的URL列表,下一行的script是标明处理这个URL的脚本,后面自己写的。如果在url字段中用 了正则表达式,则将请求传入脚本时会自动将匹配的字符串作为参数。后面的那些静态文件和登录啥的没细看,看到再写。
然后就是里面的helloworld.py文件了,最简单的就是三个print,当时看到我直接喷了,真的。 简单的不能再简单的代码了。
print 'Content-Type: text/plain' print '' print 'Hello, world!' 反正就是这么简单。然后运行它的那个简单的服务器,运行时需要指明工程的目录,即包含有app.yaml文件的目录。运行后就可以通过浏览访问8080端口来测试服务 了。还好第二个程序算是有点内容了,虽然也还是HelloWorld,但是它用了webapp的框架,代码量也有点多了。
import wsgiref.handlers from google.appengine.ext import webapp class MainPage(webapp.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'text/plain' self.response.out.write('Hello, webapp World!') def main(): application = webapp.WSGIApplication([('/', MainPage)], debug=True) wsgiref.handlers.CGIHandler().run(application) if __name__ == "__main__": main() 在main函数中,应该是通过WSGIApplication确定了对于某些特定的请求,使用哪个类来处理,get()方法用于响应HTTP GET的请求,其它的函数还没细看。返回结果和上一个差不多,嗯。
最后需要把程序部署到google的服务器上,使用它的appcfg.py上传,需要把app.yaml中的那个application改成申请下来的id,然后上传 ,输入邮箱,密码啥的。然后就可以通过 http://.
在groups上瞎逛,看到了这个,觉得满有用的,于是复制到这里一份。
在循环中使用enumerate可以同时取得循环次数和循环变量的值,使用方法是这样的
1 for i,v in enumerate(['a','b']): 2 print i,v 内置的函数,从2.3版加上去的。在这记一笔……
最近在整理个东西,本来想用LaTeX做的,但是想想它的代码高亮实在麻烦,而且默认的情况下只有黑白的,真的很难看的;而且最终发布是PDF,有时也不是很方便,所 以考虑用网页的形式弄。不想为这玩意再架个服务器,想来想去,能用好的大概就是 reStructuredText 了。
说是想到了reStructuredText,其实一开始是想自己写一个的,大概也不外乎是标记分析啥的,主要是想要 pygments 带的语法高亮,只是在网上找东西的时候,突然发现 pygments 已经支持了rst的编写,于是就打消了造轮子的想法。毕竟,现在能把文档整理出来是最重要的。但 是用的时候碰到了点问题,它是通过rst的directive支持扩展的。一开始是通过easy_install的包没有那个rst-directive.py的文件 ,使用hg弄下来的代码里面才有;弄下来后紧接着就是安装directive。折腾了半天,直到今天才找到一个网页上有大概的步骤,照做,然后一切搞定。
首先需要把那个rst-directive.py文件拷到docutils/parsers/rst/directives/下,然后再在那个directives目 录下的__init__.py中加一行,‘sourcecode’: (‘rst-directive’, ‘pygments_directive’), 至于加哪,就在类似的地方加吧,里面有一堆directives的,这样就算注册了,然后在rst文档中,就可以使用.. sourcecode这个directive了,rst会自动调用rst-directive中的pygments_directive来处理。
这样处理还不行,因为pygments默认只是把程序通过词法分析器拆开后,归到一个一个的class下,还需要CSS才能生成带颜色的东西。在网上找它的CSS文件 的时候,碰到了一个有用的命令:
pygmentize -S default -f html 这样它会在 stdout 输出CSS,直接重定向到文件即可。在rst2html中使用时,可以通过– stylesheet等参数设置使用的CSS,好像默认它会把这些CSS嵌入到网页中去,嗯。
OK了,还是满不错的,代码好看多了,嗯 ^_^