<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[limodou的学习生活]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[Python, open source, ...]]></description>
<link>http://hi.baidu.com/limodou</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[Jython中数组的生成]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/4ffd1138918cdbfab311c71d.html]]></link>
        <description><![CDATA[
		
		比如在Java中有byte []，那么如果需要在Jython中传入这样的参数怎么办呢？可以使用jarray模块。如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">jarray</font><br><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#000000">s</font> <font color="#0000c0">=</font> <font color="#0000c0">[</font><font color="#0080c0">10</font><font color="#0000c0">,</font> <font color="#0080c0">20</font><font color="#0000c0">]</font><br><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#000000">a</font> <font color="#0000c0">=</font> <font color="#000000">jarray</font><font color="#0000c0">.</font><font color="#000000">array</font><font color="#0000c0">(</font><font color="#000000">s</font><font color="#0000c0">,</font> <font color="#804000">'b'</font><font color="#0000c0">)</font><br><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#000000">a</font><br><font color="#000000">array</font><font color="#0000c0">(</font><font color="#804000">'b'</font><font color="#0000c0">,</font> <font color="#0000c0">[</font><font color="#0080c0">10</font><font color="#0000c0">,</font> <font color="#0080c0">20</font><font color="#0000c0">]</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
使用jarray.array就可以生成数组。而且它是一个通用的功能，根据第二个参数的不同，可以生成不同的类型。对于不同的类型，可以使用不同的类型代码，如：<br>
<br>
z Boolean<br>
c char<br>
b byte<br>
h short<br>
i int<br>
l long<br>
f float<br>
d double<br>
<br>
如果要转换的没有对应的类型代码，可以直接使用类，比如：java.lang.Byte。<br>
<br>
不过对于byte，Python中没有分得很细，要么是字符串，要么是整数。而Java中的byte是带符号的，因此，如果你把一个16进制的字符串想转为一个Byte，怎么做？<br>
<br>
int('0xff', 16)<br>
<br>
这样得到一个整数。然后：<br>
<br>
java.lang.Byte(int('0xff', 16))<br>
<br>
但是直接使用java.lang.Byte对象来生成数组是不行的，如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br>  4 <br>  5 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">java</font><br><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#000000">jarray</font><font color="#0000c0">.</font><font color="#000000">array</font><font color="#0000c0">(</font><font color="#0000c0">[</font><font color="#000000">java</font><font color="#0000c0">.</font><font color="#000000">lang</font><font color="#0000c0">.</font><font color="#000000">Byte</font><font color="#0000c0">(</font><font color="#0080c0">255</font><font color="#0000c0">)</font><font color="#0000c0">]</font><font color="#0000c0">,</font> <font color="#804000">'b'</font><font color="#0000c0">)</font><br><font color="#000000">Traceback</font> <font color="#0000c0">(</font><font color="#000000">most</font> <font color="#000000">recent</font> <font color="#000000">call</font> <font color="#000000">last</font><font color="#0000c0">)</font><font color="#0000c0">:</font><br>  <font color="#000000">File</font> <font color="#804000">&quot;&lt;stdin&gt;&quot;</font><font color="#0000c0">,</font> <font color="#000000">line</font> <font color="#0080c0">1</font><font color="#0000c0">,</font> <font color="#0000ff"><strong>in</strong></font> <font color="#0000c0">&lt;</font><font color="#000000">module</font><font color="#0000c0">&gt;</font><br><font color="#000000">TypeError</font><font color="#0000c0">:</font> <font color="#000000">Type</font> <font color="#0000ff"><strong>not</strong></font> <font color="#000000">compatible</font> <font color="#0000ff"><strong>with</strong></font> <font color="#000000">array</font> <font color="#000000">type</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
可以看到类型不对。这时可以使用java.lang.Byte的intValue()就可以了，如：<br>
<br>
<table border="0">
    <tbody>
        <tr>
            <td align="right" valign="top">
            <pre><font face="Lucida,Courier New" color="#000000">  1 <br>  2 <br>  3 <br></font></pre>
            </td>
            <td valign="top">
            <pre><font face="Lucida,Courier New"><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#0000ff"><strong>import</strong></font> <font color="#000000">java</font><br><font color="#0000c0">&gt;&gt;</font><font color="#0000c0">&gt;</font> <font color="#000000">jarray</font><font color="#0000c0">.</font><font color="#000000">array</font><font color="#0000c0">(</font><font color="#0000c0">[</font><font color="#000000">java</font><font color="#0000c0">.</font><font color="#000000">lang</font><font color="#0000c0">.</font><font color="#000000">Byte</font><font color="#0000c0">(</font><font color="#0080c0">255</font><font color="#0000c0">)</font><font color="#0000c0">.</font><font color="#000000">intValue</font><font color="#0000c0">(</font><font color="#0000c0">)</font><font color="#0000c0">]</font><font color="#0000c0">,</font> <font color="#804000">'b'</font><font color="#0000c0">)</font><br><font color="#000000">array</font><font color="#0000c0">(</font><font color="#804000">'b'</font><font color="#0000c0">,</font> <font color="#0000c0">[</font><font color="#0000c0">-</font><font color="#0080c0">1</font><font color="#0000c0">]</font><font color="#0000c0">)</font></font></pre>
            </td>
        </tr>
    </tbody>
</table>
<br>
BTW: 刚看到3月9日，Jython 2.5b3发布了，修复了我以前说的关于from xxx import *的Bug。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Jython">Jython</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/4ffd1138918cdbfab311c71d.html#comment">查看评论</a>]]></description>
        <pubDate>2009-03-13  19:32</pubDate>
        <category><![CDATA[Jython]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/4ffd1138918cdbfab311c71d.html</guid>
</item>

<item>
        <title><![CDATA[StyledTextCtrl语法高亮使用的探讨]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/1e8ad5077200fdc57a8947c7.html]]></link>
        <description><![CDATA[
		
		原来是想投稿的，但是编辑们认为太具体了，范围太窄，没人采用。所以一直也没有发表过，也不曾公开过。不过正好有网友问到这个问题，我找了出来放到网上。从这里<a href="https://www.box.net/shared/508zt4amao" target="_blank">下载</a>。有文章和源码。<br>
<br>
文章描述了内置的Lexer的使用和自定义的Lexer的使用。不过它是一个精简版本，Ulipad对于自定义Lexer作了增强。有兴趣可以去看Ulipad的源码。主要是 NCustomLexer.py ，可以使自定义语法高亮更容易。同时在Ulipad的英文文档 howto_write_custom_syntax_support.htm 中我也写过如何使用它，可以看一看。另外有许多Lexer就是使用NCustomLexer来处理的都可以看，比如：<br>
<br>
mixins/LexerRst.py  处理reStructuredText<br>
plugins/djangoproj/DjangoTMPLexer.py 处理Django模板<br>
plugins/mako_plugin/MakoTMPLexer.py 处理Mako模板<br>
<br>
等等。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Ulipad">Ulipad</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/1e8ad5077200fdc57a8947c7.html#comment">查看评论</a>]]></description>
        <pubDate>2009-03-11  18:28</pubDate>
        <category><![CDATA[Ulipad]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/1e8ad5077200fdc57a8947c7.html</guid>
</item>

<item>
        <title><![CDATA[StyledTextCtrl不支持screen reader :(]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/1be4d788e30e9f9ca4c272be.html]]></link>
        <description><![CDATA[
		
		今天一位外国朋友问我的UliPad不支持screen reader，刚开始不太明白，于是我试了灵格斯，可以抓文字。但是我问了他什么叫screen reader，才搞明白screen reader大部分是给盲人和弱视的群体使用的软件，因为他们无法阅读屏幕，所以需要读屏的软件。这种软件可以把你的屏幕直接读出来，比如：鼠标的移动会有不同的声音，让你很容易就知道大概的位置。鼠标放在某个窗口就可以自动将内容读出来。他还特别告诉我了两个软件：Jaws和nvda。而且nvda是使用Python开发的。不过大部分的软件对于微软的控件支持比较好。而Ulipad是使用了Scintilla的版本StyledTextCtrl。<br>
<br>
那么为了测试，我下载了nvda，是从一个叫<a href="http://www.mangren.org/" target="_blank">自强盲人网</a>的地方。以前我从来没有去过这样的地方。甚至还搜到一个叫晴天小站的Blog，他的作者杨永全就是一位盲人。这里有他的一份<a href="http://www.qt06.com/read.php/1.htm" target="_blank">介绍</a>。看到他的眼睛让我有一种说不出的感觉。我感谢我现在生活得很好。<br>
<br>
还是说一说nvda吧。启动后，鼠标的移动有声音，自动念的中文，不过效果不是太好。放在Ulipad中不知道念得什么，反正不是文件的内容。但是使用EditPlus打开相同的内容却可以自动念。因此我想，这个可能才是那位外国朋友想要的功能。于是在google上查了一下，很早就有这个问题，说是Scintilla的1.62版本就可以解决。不过现在版本应该早就过了，但是还是有这样的问题。很失望。<br>
<br>
很希望Ulipad可以让帮助更多的人。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Ulipad">Ulipad</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/1be4d788e30e9f9ca4c272be.html#comment">查看评论</a>]]></description>
        <pubDate>2009-03-09  22:55</pubDate>
        <category><![CDATA[Ulipad]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/1be4d788e30e9f9ca4c272be.html</guid>
</item>

<item>
        <title><![CDATA[关于Learning Uliweb的邮件回复－－uliweb区别于其它框架的特点]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/4ffd1138b2d6fafab311c75b.html]]></link>
        <description><![CDATA[
		
		写得很匆忙，也有不少错字，主要是基于我对django和web2py的体验，其它的象tg, pylons实在是没有用过。贴在下面：<br>
<br>
－－－－－－－－－－－－－－－－－－－－－－－<br>
<br>
&gt; 首先向Limodou表示一下敬意。能够长期从事开源软件开发的爱好者不多，而其中大多数人往往更愿意写code而不太愿意写好文档。Limodou为 Uliweb动手著书，实在是有大气。<br>
&gt;<br>
&gt; 关于Uliweb，想提个问题。我不止一次在Limodou介绍uliweb的片言只字里看到这样的提法：&ldquo;我用过xx框架，但后来有许多设计上的观点不被接受，于是我渐渐远离了xx&rdquo;。那么能否先高屋建瓴地对比一下uliweb与其它框架的不同之处、uliweb的某个特别设计又好在什么地方呢？<br>
<br>
<br>
在uliweb的文档architecure.rst中我描述了uliweb的整个架构。说简单也简单，就是将app的管理机制尽可能的做到独立。一个app就是一个开发单位，这种设计并不是uliweb新创造出来的，也是在我学习了django之后学过来的。正象在书中许我地方，我也会强调某个点是从哪个框架学来的，这是很正常的。除了app的机制外，还把其它框架中我认为好的地方尽可能的集中起来，不能说uliweb就一定比其它的好，只不过从个人角度来说，我认为是不错的。<br>
<br>
1. app管理。 django的app管理正如你下面所写的，我认为不完善。这一点其实在邮件列表中也有多次讨论。当然也并不是大家都赞同，许多人还是认为django的好。所以，选择一个框架最重要的是先要选择它的思想，思想对路的话，你可能会接受它的缺点，但是思想不对路，你可能只看到缺点。而uliweb也是这样的，它只是我个人web开发经验（其实我的经验可能不如你们许多人，只不过我希望把我的一些开发经验通过框架形成一种重用的形式，再尽可能让大家利用这种重用来积累经验。许多框架也都是这样，但是重用与重用是不同的，有些易于重用，有些不易于重用。这就是设计上的区别了）。对于django（0.97版之后就没有怎么研究了），app只能重用象template, views, urls，而static，配置都没有重用的机制。所以uliweb在这点上做了扩展。主要原因就是一个app是开发单位，而一个功能的实现除了有模板，view的处理，url的映射，还有象css, image之类的资源文件和配置信息。这些能做到重用，才会使用app的重用更方便。这里与django的比较主要是从哪个更方便来说的。<br>
<br>
再说一说与web2py的比较。web2py也有阵子没有关注了，虽然我经常在看。它的app是运行单位，不是功能或开发单位。所以app之间的重用很麻烦，不符合我的要求。这是最主要我离开web2py的原因。<br>
<br>
2. views的方便性。这一点是从web2py来的。在web2py中不需要定义request, response等变量，可以直接使用。这就减少了象django中的要定义request参数的麻烦。也许不是一个很重要的变化，但的确可以减少代码。同时，response也是自动有一个缺省的，这样你可以直接使用，并不需要象django一样，一定要定义一个Response对象。所以这块也有简单。再有就是模板的自动映射。在web2py和uliweb中，当返回一个dict时，会自动查找一个同名的模板文件，因此非常方便。而django是要指定的，我认为麻烦一些。同时response.template可以更换模板文件。最差的也可以调用模板函数手动去处理，就和django没什么区别了。<br>
<br>
3. url的映射。我使用的是werkzeug的route模块。它的定义类似于django，但是它基本上不需要写正则表达式，比如&lt;filename&gt;这就是一个匹配，在django中是要写成正则式的，这一点比较麻烦。同时werkzeug还支持一些参数，如定义GET,POST等，可以实现REST的方式。还提供了url_for这种机制(这是后来django才有的)。所以从url的定义上，我认为django的还不够方便，许多route库都不需要定义原始的正则式。这块django做得还不够方便。<br>
<br>
再说一说映射。我是定义了一个decorator，可以在views中对view函数进行修饰，也支持自动生成urls.py，在urls.py中集中定义，因此没有单独的urls.py，也不存在include的功能。因为url的绑定是放在views.py中的，因此当复用app时，并不需要修改集中的urls.py(一般也没有）。另django则需要修改。<br>
<br>
但是web2py的方式我也不喜欢。首先它是controller/action/function的方式，你并不需要绑定url，它是固定格式。但一旦你想写的话，就是写一个route.py的文件，里面面用正则式来写如何转换。曾经我写过一个使用其它的route的模块来处理url，但是要修改核心，作者不同意。<br>
<br>
4. 模板。这是我在邮件列表中讨论过多次了。django的模板看上去是挺好，但是由于象if, for,基于是不能动态创建变量这种基本功能的缺失，在处理复杂处理时，而这些处理正好是为了显示才做的，非常麻烦，甚至要手写tag。现在django的tag不可谓不多了，已经是一门独立的语言了，看一看djangosnippets就知道了，有好有坏，django的团队我看是基本上不关注的。我还曾经想，会不会定期把一些好的tag合到django中去，但是没有见过有这样的行为，也许是我没有看到。为此我还写过一些tag，还有一些外国朋友问把我的expr之类的tag加入他们的项目需要什么样的license。如果django的模板稍微多一点工作，我写的许多的tag都没有存在的必要。所以我最终选择了web2py的模板。它支持python代码的嵌入，支持必要的tag，如extend, include等。语法一致，如都是放在{{}}中的。而django是使用{%%}和{{}}来区分。在web2py中都一样。同时使web2py，不用关心缩近，它会自动处理，但是要在块结束的位置加上pass，这是python的空语句。<br>
<br>
但是web2py的模板不支持block，我认为这是django模板中一个非常好的功能，于是我做了扩展，加上这一功能，但是这一功能我在一个web2py的邮件中作了回复，没有感兴趣。现在我还扩展了支持自定义tag，不过比较简单。因为可以使用python代码这一功能基本上不需要。你也可以向模析台注入新的方法和函数在模板中直接使用。另外web2py的模板可以编辑成py代码，象mako一样可以存在一个临时目录，不过这也是我扩展的。现在的uliweb的模板是从web2py模板发展来的，但是做了许多的改进。<br>
<br>
5. settings 在django中是使用python源码，很多人都喜欢。我原来也喜欢。但是前面说到了一个原因是每个app没有自已的setting，因此限制了重用的方便性。同时python源码造成它的形式会非常灵活，而不方便通过程序进行改写，如果你想写一些安装工具时，这种方式非常困难。其实许多的框架都使用ini形式的配置文件，如tg, pylons。我曾经向django建议，结果得到了很强列的反对。tg有阵子来考虑使用我的dict4ini来处理ini，不过没有使用，后来使用了ConfigObj，后来就不太清楚了。最早uliweb也是使用py文件，但是后来我还是改成了ini格式，不过可以支持基本的python语法，只不过不能使用import之类的。所以可以看成是ini与python表达式的结合。而且还支持了#coding=这种编码的定义和_()的国际化处理支持（当然要与uliweb相结合)。web2py这一点不让我满意，因为它的一个设计思想就是0配置，在我看来，一个灵活的框架与配置本来就不可分，0配置表示用户很难灵活的架建自已想要的框架，所以这也是我离开web2py的原因。再有就是web2py的作者过于强调语法的向前兼容，在我看来这是很好的，但不应是一种教条，一旦绝对化，对于以后的优化没有什么好处。<br>
<br>
6. ORM其实这倒没什么。web2py和django都是自已的。于是uliweb也搞了一个，基本语法是参考GAE的，许多代码是从GAE学来的，而GAE又是学Django的。不过我的低层是使用的sqlalchemy。所以语法也基本上是sqlalchemy。目前也支持manytoone, onetoone, manytomany,不过开发时间不长，还没有人使用，所以可能与其它的比不了。功能也不一样完整。不过与django的区别是：在django中，表级别的操作要通过manager，即Model.objects来操作，而Uliweb的ORM是直接Model.all()之类就可以了。因为它使用了descriptor来处理，所以可以直接在model类上进行，而django没有使用，所以不得以使用manger的方式，当然这也造成，你可以构造新的manager。不过在uliweb上想做也是可以的，就是在类上定义一个类方法就好了。web2py原来叫ORM，但是后来是认没有ORM的功能，所以改为DAL（数据库抽象层）。可比性不高。<br>
<br>
7. i18n。都有这功能。uliweb的i18n是自已做的，但对于翻译函数的处理是学django的。不过因为uliweb的模板可以转换为python代码，所以处理上要比django简单。而web2py的国际化处理并没有使用标准的gettext，是通过定义一个T，然后自动抽取，处理模式不同。uliweb的i18n处理学习了django的，可以从cookie,<br>
session, 配置中得到语言设置。<br>
<br>
8. uliweb有一个form库，是自已写的。可以不用。支持象django一样的定义，校验，validator的使用，比效OO。而web2py则看上去是HTML代码与form处理的一个混合体，不是很OO。<br>
<br>
9. 其它uliweb的特点。有一些是别的框架已经有的：<br>
<br>
* django风格的middleware<br>
* wsgi middleware的支持，目前测试比较少，现在的staticfiles就是一个middleware<br>
* app之间可以定义依赖，放在config.ini中，这样在导入一个模板时将自动将依赖的app自动添加。而django没有这种机制。这样可以简化对settings.ini的修改。<br>
* 部分地方使用pkg_resource进行处理。django从使用setuptools后来放弃了，改成原来的disutils。<br>
<br>
&gt; 就目前我从《Learning Uliweb》中感觉到的，貌似Uliweb的重点在于追求重用，实现这一点的手段就是settings.ini。不知道这个理解是否片面？<br>
&gt;<br>
&gt; 摘录《Learning Uliweb》中的一小段。<br>
&gt; 在前面你看到app可以有自已的settings.ini，可能你会问为什么这样设计？答案是：为了重用。在Django中你做不到，甚至django中不提供static目录的支持。那么这样的结果是：所有的app的配置信息都放在了settings.py中，所以有app相关的静态文件被放在了一起。对于单个项目是没有关系，但是一旦你想把其中的某个app拿出来复用就会非常麻烦，你可能很难找到哪些是与这个app相关的。而一个app的功能是<br>
&gt; 多方面的，需要的资源也是多样的，配置信息就是其中一种。因此，这就是Uliweb的设计。<br>
<br>
<br>
重用在其它的地方，如GUI之类的似乎要容易得多，而web开发要复杂得多，因为一个功能可能涉及到许多的内容，如css, images, template, views, url等等。虽然它们分散存在，但是却是为了完成一个功能。所以这就是uliweb对app的理解。而前面所说的app的依赖的处理也是充分了考虑重用也设计出来的。为什么软件开发做不到象盖房子那样，一方面创造性，不缺定性造成的，另一方面我认为可能还是重用性设计得不够。<br>
<br>
以上只是匆忙想到的，主要是个人主观感受。一个框架必然有它的思想在里面，所以uliweb不会适合每一个人。<br>
<br>
<br>
<strong>update 2009.3.1 又新添加了些回复，主要是针对于web2py的：</strong><br>
<br>
&gt; 谢谢Limodou推心置腹的交流。我没有用过Django，近期用得多的是web2py，所以以下对Limodou提到的方面，说说我在使用web2py过程中的理解或者处理手法，请Limodou指点。<br>
&gt;<br>
&gt; 1. 关于app的管理，或者说关于&ldquo;重用&rdquo;。不错，和GUI相比，WEB开发之中， 涉及到&quot;css, images, template, views, url等等，虽然它们分散存在，但是却是为了完成一个功能&rdquo;。而我觉得app就是包含以上各<br>
&gt; 个内容的超集，所以完全可以把完成某种通用功能的一批css,images,template,views等东西组织在一个通用app之中，然后其它的业务app通过类似webservice的方式来调用通用app中的内容。感觉上这样的效果也许用起来不如uliweb本身内建重用机制那么天然，但最终实际效果差不多。况且从我的个人体会来看，web开发要用到的个把css或image之类的，不就是几个文件嘛，大不了就手动copy一个副本，这样至少有一个好处是一个app按自己需求调整个把css，也不会影响到其它的app。追求重用是好，但如果过了头，那么紧耦合的一些缺点也会出现。<br>
<br>
<br>
重用并不表示不可以调整。就象我前面所写的，重用与重用不同，有些重用简单，有些重用要手工改许多东西。易用性的差别往往就那么一点。这么多的框架，从功能上讲那个都差不到哪里去，但是为什么有人喜欢这个，有人喜欢那个，可能就是因为这一点点。web2py的service是应用级别的重用，从更高层的划分它只是一种重用的方式。其实在许多时候我们只想要重用一些静态文件，功能，并不是一个完整的service级别的重用，因此web2py的这种重用对于这种情况很麻烦。所以效果差不多要看具体的情况，我不认为差不多。至于拷贝文件，正是许多人认为无所谓破坏了易用性。对于已经非熟的人，你怎么做都会认为无所谓，因为everything in the control，但是对于初学者这之前的差异就很大。甚至到了一些UI的交互设计上，甚至要考虑如何减少一次点击，少一次按键。也许是过头，但是如何表示这种设计就是过头了呢？何况这种设计，你可以看到，并不是很困难。许多时候，开发者多想一点，多做一点，就会给使用者非常大的方便。让别人方便我不认为是过头。而紧耦合性的缺点也只是理论上，如果有，自然要想办法去解决了。所以有问题并不可怕，这正好是设计与实用性的一个平衡问题。<br>
<br>
&gt;<br>
&gt; 另外，如果Limodou有持续关注web2py的话，可能也已经注意到它先后发展出的T2、T3插件。简单来说就是从&ldquo;模式&rdquo;的高度去定义并实现了WEB开发过程当中的一些常见需求，例如用户认证、极限管理、数据搜索、分页呈现……等等。看来web2py不是不重视重用，但走的是另外一种路子，重用的是模式。<br>
这些我了解得很少T2我看了一点文档。未来uliweb可能也会向这方向来走。不过我以前在blog也说过，框架应该是分层的，最底层是给平台构建人员使用的，将用来构建满足自已团队需要的环境。然后是最终用户，他们将在新的平台上进行工作。所以uliweb目前还主要在完成底层的构建，对于平台还在摸索和积累中。而web2py已经在开始提供我认为的平台层了。这是更高层的复用，这一点我并不否认。只不过要看它是以何种方式来复用，是通过app还是别的。这一点我的确没有太多了解。因为web2py的app是独立可运行的，从这一点它很难做到细粒度的功能复用。因为它里面的功能并没有分开，所以与我的要求不满足。<br>
<br>
&gt;<br>
&gt;<br>
&gt; 2. uliweb的view方面和web2py的controller看来是差不多，就不说什么了。<br>
&gt;<br>
&gt;<br>
&gt; 3. url映射。django的url映射要用到正则表达式，这是我从一开始就没有选择学习django的最大原因。:) 正则表达式的功能是强大，但学习起来的门槛也较高。君不见咱这python-cn列表，问django里怎么写某个URL或者问怎么写正则的邮件，多了去了。在合适的场合用正则，事半功倍；在不必要的场合用正则，自讨苦吃。<br>
&gt;<br>
&gt; 扯远了。说回web2py的url映射，固然是固定了只能用/app/controller/function的方式，但实际使用之中也没觉得有什么不方便呀。无非就是对于那些访问了不存在的路径的请求，无法全部捕获并转到某个通用的错误处理函数罢了。也基本不影响使用，因为正常情况下用户是在我们app的菜单之中选择操作，不应该需要自己输入某个错误的URL的。在这里我没有领会到要有更灵活的url映射机制的必要性，权当是一种锦上添花的功能吧。<br>
<br>
<br>
web2py也支持将/app/controller/function映射为其它的url的形式，但是需要定义一个route.py，而且要使用正则式。uliweb则使用简单的route规则，比正则式要简单，所以我认为是一个比django正则式更好的方案。而且uliweb的expose函数，有一个特点，比如<br>
<br>
@expose<br>
def index()<br>
<br>
可以看到，我并没有指定url，但它可以直接映射为/app/views/function，很象web2py。灵活性是功能的要求，而不是个人的要求。当然也可以看到是我的要求。虽然你不需要，但并不表示我或其它人不需要。在django中专门就url有一个说明，它说好的url是设计出来的，我很赞同。另外就是uliweb的expose支持一些方法，如是否只匹配GET或POST，可以实现REST的风格。这又可以让一些人高兴。框架虽然不会让每个人高兴，但是如何可以让更多人高兴，为什么不去做呢？我反正是很少坚持我个人的哲学（当然我也会有），但是如果改动不大，我很乐意考虑加入一个新特性。<br>
<br>
<br>
&gt;<br>
&gt;<br>
&gt; 4. 模板。web2py的模板倒是有extend和include的指令，本来就是用于扩展缺省layout模板的。和block的效果有点接近吧。<br>
&gt;<br>
&gt; 另外就是可能在MVC（或MTV）分层思路的角度，template里通常不应该存在太复杂的业务逻辑，所以估计不支持block的实际影响也不大。<br>
&gt;<br>
<br>
<br>
extend和include在django中也有。但它是文件级别的。而block是一个文件中的一部分。在web2py中处理起来很麻烦。因为它只能定义一个{{include}}。但是一个模板可能有许多地方是可以让用户来替换的，在web2py中就不方便。这并不是什么业务逻辑，这是模板替换的要求，在实际中有这样的需求。这一点是我认为django不错的。所以我也扩展了一下。对我影响很大。比如我有一个layout模板，上面有一个{{block title}}untitle{{end}}。这个意思是说我希望title是可以替换的。但是在这个模板中至少还有{{block main}}{{end}}用来输出页面的内容。因此一个页面就有两个内容可能需要替换。那么在web2py中会怎么做？<br>
<br>
用函数吗？如果子模板没有定义怎么办？使用block时，如果子模板没有定义相应的block，则可以使用block中原来的内容。所以block一方面是指定了可以替换的内容块，另一方面还起到提供缺省值的作用。<br>
<br>
&gt;<br>
&gt; 5. settings。估计你说的setting是指配置文件。虽然web2py没有显式的setting机制，但事实上由于它在每次执行一个app时都会先导入所有相关的model文件，所以客观上开发者可以定义额外的model文件，在里面定义当前app范围内的配置项，当成配置文件那样使用。<br>
&gt; 这在web2py圈子已经是惯例了，事实上web2py的作者Massimo自己也这么干。:) 所以setting的问题应该是互相等价吧。<br>
你说的model是指什么？是数据库定义的model还是什么？这一功能是与app复用相关的，但是由于web2py不支持细粒度的复用，所以这一功能对于web2py的意义不大。因为它的一个app就是一个运行单位，而且一个app内部又没有细分，所以不存在我说的情况。<br>
<br>
&gt;<br>
&gt; 至于说web2py是否&ldquo;过于&rdquo;强调语法的向前兼容，这个见仁见智了。不过要看到，web2py在承诺保证对1.0版的所有语法都永远保持兼容的前提下，也以极快的速度增加新功能。手法很简单，新的东西以新的API出现，但旧的东西保持不变。我认为这很好地平衡了兼容性和扩展性。<br>
&gt;<br>
<br>
<br>
这一点我曾经向作者建议过。有时候为了引入新功能，兼容性的破坏是可以接受的。甚至如果用户都说无所谓，作为开发者一定要坚持是否有必要，更何况以前的版本还有多少个人在用。是否兼容我看是要看以前的版本是否还需要继续支持，不然，没人用的东西我还坚持它作什么？现在的软件更新都很快，大家也喜欢用新的版本。特别是对于一个新生的框架，用的人没几个，考虑太多反而没有必要。所以坚持不坚持要看实际的情况，不是一成不变的。如果以前的版本仍然有许多人在用，是可以考虑兼容性的。我并没有说一定不兼容，只不过不希望兼容变成框架发展的一个限制而已。<br>
<br>
&gt;<br>
&gt; 其它的好象差别不大，就不多说了。<br>
<br>
谢谢交流。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/4ffd1138b2d6fafab311c75b.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-28  12:28</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/4ffd1138b2d6fafab311c75b.html</guid>
</item>

<item>
        <title><![CDATA[将Learning Uliweb中的配套代码放在了uliweb-tests中了]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/e2c10d33496317ff1a4cffb5.html]]></link>
        <description><![CDATA[
		
		可以从 http://code.google.com/p/uliweb-tests 中找到。现在第4章已经基本完成。越往后可能进度越慢，因为一方面讲得东西会越来越多，越来越深，另一方面测试的代码会越来越复杂。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/e2c10d33496317ff1a4cffb5.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-25  22:49</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/e2c10d33496317ff1a4cffb5.html</guid>
</item>

<item>
        <title><![CDATA[使用Ulipad的Python代码渲染功能]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/5e6b7acbc00a0b18be09e692.html]]></link>
        <description><![CDATA[
		
		在 17xie 上已经开始了《Learning Uliweb》的写作，到目前已经进入第三章的写作，不过是最简单的Hello的讲解。那么我遇到一个问题是代码高亮怎么办。后来想起来Ulipad本身就有代码转换成HTML的功能，并且可以直接打开浏览器看到结果。所以就用它将转换代码，然后贴到web编辑器中。效果还不错。百度的Blog也可以这么干。<br>
<br>
使用方法：<br>
<br>
1. 先选中要处理的Python代码<br>
2. 点右键在弹出菜单中选Convert-&gt;Output to HTML Window(或在Edit菜单也可以找到Convert菜单)，这只是一个配置项，是不能输出的<br>
3. 然后再点右键，在弹出菜单中选Convert-&gt;Py to HTML，就可以看到弹出一个HTML窗口，有转换后的Python高亮代码。选中，拷贝就行了。<br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Ulipad">Ulipad</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/5e6b7acbc00a0b18be09e692.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-24  17:55</pubDate>
        <category><![CDATA[Ulipad]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/5e6b7acbc00a0b18be09e692.html</guid>
</item>

<item>
        <title><![CDATA[开始写《Learning Uliweb》]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/acbe94ca93575081c817682c.html]]></link>
        <description><![CDATA[
		
		地址在<a href="http://www.17xie.com/book-32498995.html" target="_blank">这里</a>。这是一个写书的网站很有意思，因此打算试一试。进度要看时间了，想到什么写什么。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/acbe94ca93575081c817682c.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-23  21:38</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/acbe94ca93575081c817682c.html</guid>
</item>

<item>
        <title><![CDATA[pygettext不支持ngettext]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/f5788c100794cc06203f2e42.html]]></link>
        <description><![CDATA[
		
		Uliweb中使用修改过的pygettext版本，但是现在发现它不支持ngettext(msg1, msg2, n)这种形式。在网上也查到了这个问题，现在许多是使用xgettext工具。之所以使用pygettext是因为它是源码的，可以方便处理模板中的翻译字符串，且不需要安装其它的软件。现在先这样用吧。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/f5788c100794cc06203f2e42.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-22  21:49</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/f5788c100794cc06203f2e42.html</guid>
</item>

<item>
        <title><![CDATA[增加Timezone功能]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/0e35a5c22364261c0ff47747.html]]></link>
        <description><![CDATA[
		
		把timezone功能加进去了，结合前面我对pytz的研究，我写了一个date.py的模块，可以进行有关时区的转换。比如通过：date.set_timezone(tzname)可以设置一个缺省的时间，它可以对其它的有间函数起作用。<br>
<br>
几个有用的函数：<br>
<br>
now(tzinfo=None)可以得到当前时间<br>
today(tzinfo=None)可以得到当前的日期<br>
to_timezone(dt, tzinfo=None)可以将一个datetime对象转为指定的时区<br>
to_date(dt, tzinfo=None)将一个datetime对象转为date对象<br>
to_time(dt, tzinfo=None)将一个datetime对象转为time对象<br>
to_datetime(dt, tzinfo=None, format=None)将一个date, time, datetime, string对象转为datetime对象<br>
<br>
以上方法当tzinfo为None时使用的是缺省的__timezone__值。而这个值是可以通过set_timezone(tzname)来设置的。<br>
<br>
那么这个功能是在SimpleFrame.Dispatch初始化时，根据settings.ini中的TIME_ZONE的值，调用date.set_timezone(settings.GLOBAL.TIMEZONE)来设置的。缺省是UTC时间。<br>
<br>
因此当你想使用这种功能时，一定要使用date提供的方法来生成时间对象。<br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Uliweb">Uliweb</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/0e35a5c22364261c0ff47747.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-22  15:09</pubDate>
        <category><![CDATA[Uliweb]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/0e35a5c22364261c0ff47747.html</guid>
</item>

<item>
        <title><![CDATA[关于pytz的一些记录(续)]]></title>
        <link><![CDATA[http://hi.baidu.com/limodou/blog/item/987ea8ec3dfa902063d09ff7.html]]></link>
        <description><![CDATA[
		
		在昨天与了关于pytz的东西后，还是发现一些问题。<br>
<br>
&gt;&gt;&gt; import pytz, datetime<br>
&gt;&gt;&gt; tz = pytz.timezone('Asia/Shanghai')<br>
&gt;&gt;&gt; tz<br>
&lt;DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD&gt;<br>
<br>
可以看到，它有一个<strong>LMT</strong>，这是Local Mean Time的缩写，网上查一查意思是本地平均时。而且时间是+8:06，说明与UTC的时差不是8个小时整。先不管它，让我们转换一下试试。<br>
<br>
&gt;&gt;&gt; d = datetime.datetime(2009,2,21,23,18,5,tzinfo=tz)<br>
&gt;&gt;&gt; d<br>
datetime.datetime(2009, 2, 21, 23, 18, 5, tzinfo=&lt;DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD&gt;)<br>
<br>
好，时区与tz是一样的，没什么。<br>
<br>
&gt;&gt;&gt; x = d.astimezone(pytz.utc)<br>
&gt;&gt;&gt; x<br>
datetime.datetime(2009, 2, 21, 15, 12, 5, tzinfo=&lt;UTC&gt;)<br>
<br>
我们转为了UTC时区，时间上有差异，没问题。<br>
<br>
让我们再转回来。<br>
<br>
&gt;&gt;&gt; x.astimezone(tz)<br>
datetime.datetime(2009, 2, 21, 23, 12, 5, tzinfo=&lt;DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD&gt;)<br>
<br>
奇怪，看到了吧，变成了<strong>CST</strong>了。时差也成了+8:00了。CST就是Central Standard Time的意思。但这样就造成了转换的不一致。我们应该使用CST标准才对。<br>
<br>
让我们再看一下：<br>
<br>
&gt;&gt;&gt; datetime.datetime.now(tz)<br>
datetime.datetime(2009, 2, 22, 11, 11, 2, 125000, tzinfo=&lt;DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD&gt;)<br>
&gt;&gt;&gt; datetime.time(23, 18, 5, tzinfo=tz)<br>
datetime.time(23, 18, 5, tzinfo=&lt;DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD&gt;)<br>
<br>
可以看到now()函数得到的是CST的，而time传入tzinfo是LMT的。（date不支持tzinfo参数）所以我们要进行修订，怎么做，使用timezone对象的localize()方法，如：<br>
<br>
&gt;&gt;&gt; d = datetime.datetime(2009,2,21,23,18,5)<br>
&gt;&gt;&gt; tz.localize(d)<br>
datetime.datetime(2009, 2, 21, 23, 18, 5, tzinfo=&lt;DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD&gt;)<br>
<br>
所以我才明白pytz的文档上说的：<br>
<br>
Creating localtimes is also tricky, and the reason why working with local times is not recommended. Unfortunately, you cannot just pass a &lsquo;tzinfo&rsquo; argument when constructing a datetime.<br>
<br>
所以我的建议是生成带时区的时间时，一定要使用timezone.localize()来生成。不要在时间对象的构造函数中传入tzinfo的方式来实现，为些我封装了一些函数放在了uliweb/utils/date.py中。<br>
<br>
另外关于北京时间。在pytz中，我无法找到Asia/Beijing和GMT+8这样的时区设置，但是有些时间转换的工具却有。按理说pytz使用的是标准的时区数据库，我特意下载了查看，的确是没有。<br>
<br>
时区处理的确是挺麻烦的事。象有些数据库也支持这样的功能，如postgres支持set timezone的命令，这是在django中看到的。<br>
<br>
<br>
<br> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/limodou/blog/category/Python">Python</a>&nbsp;<a href="http://hi.baidu.com/limodou/blog/item/987ea8ec3dfa902063d09ff7.html#comment">查看评论</a>]]></description>
        <pubDate>2009-02-22  11:20</pubDate>
        <category><![CDATA[Python]]></category>
        <author><![CDATA[limodou]]></author>
		<guid>http://hi.baidu.com/limodou/blog/item/987ea8ec3dfa902063d09ff7.html</guid>
</item>


</channel>
</rss>