在前面关于Backbone的文章里提到过要谈后端的,现在就来简单说说在那个离线客户端的后端实现中用到的一些东西。
用了很长时间的web.py,之所以选择web.py,是走过很多弯路的。早年主要是一些重量级框架,接触过Django、TurboGears和Pylons相当长时间,尤其是TG1用了很久,具体在《SD2C之三种Python的Web框架 》里说过。后来还有一段时间用了web2py——因为它是all in one。但后来发现这类重量级的框架太笨重,安装部署都麻烦,最关键的是局限性太大——且不说Django/web2py这种,全要按它们的路子走,TG1换了模板和ORM,有些功能也没了,Pylons则是换起来麻烦。于是转向轻量级的框架。
当时也没太多研究,就大致看了一下,感觉web.py比较简单,而且资源也挺丰富,就用起来了。关于web框架的选择,我曾经零散谈过几次,主要的理由有几个:
首先是轻量。重量级的框架实在是用烦了,所有的功能都要按它们设定的路子走,稍有不慎就掉坑里。除此之外还有个问题就是,它们各自的实现都不一样,一但需要切换,原来的经验全部作废,这是我不能接受的——年纪大了,从头学新东西太费事。
其次是要易学易用易部署。易学需要有简单全面的文档,各种资源相对丰富。易用是基本的功能要能简单实现——比如REST。易部署……这个只要是WSGI现在用gunicorn都容易,没什么好说的,但还有一点很关键的是尽量不要有我不认识的外部依赖。
第三就是我现在比较熟悉的SQLAlchemy和Mako模板能直接用上,我可不想再学别的ORM和模板了。
最后则是一些小原因:比如Django这种名字不好读的我就不太喜欢。还有像Flask和uliweb依赖的那个Werk什么什么的,那名字我不搜索从来就没法正确拼出,更不要说读了。
这几个条件一出,常见的web框架大部分都被毙了:Django太重,名字不好,没法简单地换掉模板和ORM。TurboGears/Pylons/Pyramid外部依赖太多。web2py局限太大,模板和ORM都没法换。flask/uliweb依赖那个我很不喜欢的Werk什么什么。Tornado之类的异步框架太不易学。于是就剩下web.py和bottle。而选择web.py完全是因为先入为主。
因为之前用了TG1很长时间,有些功能用着挺习惯,所以也在web.py下也自己打造了一堆类似的东西,于是有了这个webpyext(起初把它叫做webtg)。
使用使用方法参见前面的《Backbone笔记之三(Controller与集成) 》里的例子程序(注意:仅限目前的版本,以后计划改用bottle)。
这个项目已经发布在bitbucket——除了fork或依赖在github上现有的项目会放在github上以外,我自己创建的项目都放在bitbucket:
https://bitbucket.org/raptorz/webpyext
当然,如这个项目的说明上所说,我已经改用bottle,所以这个项目以后可能都不会再更新,仅供参考,或者有兴趣的人可以自行fork继续。
选择bottle的理由其实与选择web.py一样:轻量、无依赖、简单易用。但是放弃web.py的理由有一个:Aaron去世了。目前看来暂时还没有谁要接手web.py的迹象,所以还是换了吧。
关于bottle与web.py的比较,可以看一下令狐虫的这篇《bottlepy及其它》。
当然,对我来说换到bottle也是有不少问题的。首先就是这些为web.py写的代码大部分用不上了,我需要按bottle的方式重写一套(这个工作正在进行中)。其次是bottle的某些方面功能比web.py更弱一些,比如没有session,比如plugin+route对象的方式不如web.py的processor+web.ctx方便好用。而且bottle的插件模型与自定义decorator有冲突,也就意味着你必须将所有自定义的处理都做成插件,然后插件之间的交互又成了新的问题。
不过有失有得,bottle的request不错,甚至包括了对json请求的支持,这样的话用作backbone后端就更省事了(web.py的话,我是在这个webpyext里做了一个decorator来处理的)。
还有一个选择bottle的次要原因是它的性能略好,详见《继续小测python web server 》。更多关于webserver性能方面的比较,可参见这个《Web Framework Benchmarks》。
然后:
1、找到Zend Studio所在的文件夹 (在Windows 7是"C:\Users\[your profile]\Zend\workspaces\.metadata\.plugins\org.eclipse.core.runtime\.settings" 提示:[your profile]请自行换成你自己的目录名,如我的Zend Studio的目录在C:\Users\pzh\Zend\workspaces\DefaultWorkspace\.metadata\.plugins\org.eclipse.core.runtime\.settings)。
2、删除.settings文件夹下面的"org.eclipse.dltk.ui.prefs" 文件即可。
http://acm.hdu.edu.cn/showproblem.php?pid=2544
Dijkstra模版题,Dijkstra模版终于初步确定了
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std ; const int INF = 1000000 ; const int maxn = 105 ; int edge[ maxn ][ maxn ] ; int used[ maxn ] ; int path[ maxn ] ; int dist[ maxn ] ; int S[ maxn ] ; int n , m ; int Dijkstra( int v0 ) { int i , j , k ; memset( used , 0 , sizeof( used ) ) ; for( i = 1 ; i <= n ; i++ ) { dist[ i ] = INF ; } dist[ v0 ] = 0 ; for( i = 1 ; i < n ; i++ ) { int MIN = INF , u = v0 ; for( j = 1 ; j <= n ; j++ ) { if( !used[ j ] && dist[ j ] < MIN ) { MIN = dist[ j ] ; u = j ; } } used[ u ] = 1 ; for( k = 1 ; k <= n ; k++ ) { if( !used[ k ] && edge[ u ][ k ] && edge[ u ][ k ] + dist[ u ] < dist[ k ] ) { dist[ k ] = dist[ u ] + edge[ u ][ k ] ; } } } } int main() { int x , y , temp ; int i , j , k ; while( scanf( "%d%d" , &n , &m ) != EOF && ( n + m ) ) { memset( edge , 0 , sizeof( edge ) ) ; for( i = 1 ; i <= m ; i++ ) { scanf( "%d%d%d" , &x, &y , &temp ) ; edge[ x ][ y ] = edge[ y ][ x ] = temp ; } Dijkstra( 1 ) ; printf( "%d\n" , dist[ n ] ) ; } }