django添加pylucene失败

lucene简单易用,而且默认的中文分词也还凑合。
本来用lucene做django的全文搜索引擎应当会是个不错的选择。
不过看似乎没看到什么项目这么做,在django的世界里似乎xapian更流行些。
做过了才知道,不是没人用,而是pylucene这东西根本就没法用:(。

今天花了一晚上将pylucene的全文搜素给做完,用django自带的测试服务器测试也没啥问题。
部署到服务器上就挂了。
本还以为服务器上的部署问题。
些了个简单的测试程序到服务器上又测试了一遍。
测试程序OK。
但django还是死活跑不了。

然后想起pylucene那个比较BT的问题。
pylucene由于是CGJ编译的,为了支持垃圾回收,如果在线程中使用pylucene需要继承PyLucene.PythonThread。

到网上找了下,还真是这个问题。
据说
"import PyLucene.PythonThread as thread" in django/utils/autoreload.py
对django做这样一个修改就可以正常工作了,不过mod_python下还是无法正常使用。

我用的是fastcgi,不过修改够还是无法正常工作:(。

各位打pyluence主意的朋友们以后得主意了,pylucene这东西有时候真的不是太好玩:(。
pylucene除了gcj版本外还一个jcc版本,这个版本是用c++对java进行wrap。
应当不会有类似gcj版本的问题,但你必须安装个java。

参考资料:
PyLucene JCC vs GCJ
http://ubuntuforums.org/showthread.php?t=593327

pylucene编译成功

    Python可以使用的全文检索方案还是有几个的,其中比较流行的有Xapian(豆瓣在用)和Pylucene。
    但对于中文而言,除全文索引引擎外,中分分词也是个麻烦事。Pylucene移植自lucene,因此很自然的支持中文分词。Xapian就没这么幸运了。虽然也有些简单的方法让Xapian支持中文分词,但效果也都好不到哪去。经过斟酌之后最后还是确定使用PyLucene。
以前在Linux下安装软件基本上都是apt-get。不过共享主机就没这么方便了。在pylucene的网站上找了半天也没找到可以匹配的二进制包,于是决定手动编译pylucene。
    去看了下编译说明,似乎还比较简单,只要简单的修改Makefile就可以。可以是有个比较大的问题,服务器上没有gcj,还得先安装个gcj。
    去down了个pylucene推荐版本gcc进行编译。被那个host参数整了半天(设置得不对),后来去掉–host后将gcc编译成功。编译费时1小时?
    Pylucene的编译倒挺快,不过目录结构和Makefile中定义的目录结构似乎有些不太一样。手动将相关文件复制到对应目录后运行sample,查看运行结果。
    IndexFiles.py ./    可以看到成功索引了一个文件PlainText.txt
    SearchFiles.py     输入查询条件Plain,可以看到成功的查询出了一条记录
    到这里pylucene就已经可以正常工作了,过些天等有空就去将国学阅读网的全文索引给做。

国学阅读网上线了

网站地址:http://guoxue.victsoft.com/

    其实这个网站在很早以前就有开始整了,中途因为一些事情中断了许久。最近在假期就快结束的时候重新启动,花了几天时间做了个收尾工作,正式部署上线了。
    国学阅读网看名字就知道她是做啥的了。目前网站的功能还比较简单,只提供了书签、收藏、好友等基础功能。各书籍的点击次数等虽然也有统计,但目前还并未使用。
    类似豆瓣的网友最新动态,我觉得这是一个挺有意思的功能。他让各个网友都有露面的机会,而且越是活跃的网友露面的机会越大。这对激发网友的活跃度将会很有作用。这个功能的实现也不复杂,不过我目前优先考虑的还是网站的上线。这个功能或许很快就会推出了(说不定写完blog就去整这东西了)。
    如果说“老照片”是我的第一块试验田,那这个网站就算是第二块试验田了。“老照片”基本认定是失败的了。至于失败的原因在早前的blog中已有分析过了。
    主要两点:
    1. 缺乏必要的基础资源,无法引导用户。
    2. 图片网站对搜索引擎并不友好,SEO难度过大。
    “国学阅读网”应当也有不少问题,但至少这这两点上会比“老照片”好些。国学阅读网上的古文典籍,本身就是网站的基础资源。收藏夹、书签等功能可以为用户的阅读带来便利,有一定的实用价值。
    网站的古文典籍,本身是大量的文本信息相比图片,这对搜索引擎要友好得多。
    当然“国学阅读网”在SEO方面也个很严重的问题。古文资料在网络上已经是一大把了,而且资料是从网络上收集来的,很容易被搜索引擎打入黑名单。
    无论如何,看看新网站的表现了。

————————关于Django————————
    Django的开发速度确实挺快,就是修改表结构的时候比较郁闷。Django不能象Hibernate一样自动修改表结构。
    这个工程的项目结构在我看来有些乱。Django提倡各个模块要相对独立,这样可以提供模块的复用性。这样模块想引入新项目的时候,只需要做个简单的url配置就可以。但事实上各个模块之间要做到完全的独立似乎并不是一件容易的事,比较项目本来就是一个整体,完全独立的模块太少。项目的前期我有刻意的将模块独立,但到了后期我舍弃了这个做法。

发布:支持unicode的SQLite3控件(Delphi)

下载地址
http://2ccc.com/article.asp?articleid=4612

sqlite介绍
    sqlite是个嵌入式数据库。发布的时候只需要带上一个300K的DLL就可以,不用去担心用户没有驱动的问题。
    sqlite支持完整的sql语法,使用方便。
    综合以上优点,sqlite用来给桌面程序使用还是很不错。

sqlite4delphi(unicode)介绍
     因为刚好要用到sqlite,所以到网上去找了一个感觉不算太糟糕的sqlite控件。程序写到一半的时候发现需要增加unicode支持:(。而且根据sqlite3的规范,sqlite3中的数据都应当是以utf-8形式保存。于是动手对库程序进行了部分修改,增加unicode的支持,同时对入库数据进行utf-8编码。

使用方式
    将SQLite3.pas,SQLiteTable3.pas放到代码的搜索路径, sqlite3.dll(bin/sqlite3.dll)和可执行文件放到同一目录。在unit中引用SQLiteTable3就可以使用了。其他的更多使用方法看原作者的介绍(readme.txt)和demo。

PS:
    字符的编码方式害死人啊,老要转来转去。
    特别是delphi,对unicode的支持又不行。要界面支持unicode只能用tnt,然后其他控件集体阵亡。
    要是早统一成utf-8这世界就清净了。

要虐就一次虐个够

    话说我这次真的是受够了delphi。Delphi的unicode支持实在是太烂了,所有VCL都不支持unicode,要支持VCL只用用第三方的TNT(现在改名/收费了)。
    Delphi的一大好处就是控件多。unicode一下,那些第三方控件全部挂掉(就没几个控件是unicode的)。

发布“支持全文检索的大富翁浏览器”

下载地址:
支持全文索引的大富翁浏览器(Delphi盒子)

前言
    已经很久没有去大富翁了,后来想再去转转却发现连密码都已经忘记了。更惨的是密码找回的邮箱在去年被关闭了。这下密码是没办法用正常途径找回了。虽然有些可惜,但也算了吧相见不如怀念。
    前些天看到大富翁07年的离线数据库(非官方)发布了。在我早期玩delphi的时候大富翁的离线数据还是给了我很大的帮助的。我想从离线数据中收益的人应当不只我一个。曾有段时间离线浏览器层出不穷。当然离线数据最受欢迎的方式还是chm方式。只是随着离线数据的增大,要编译成单个CHM的难道增大。在04(03?)年后,chm版的离线数据就变成按年分的了。
    我想chm版的流行和良好的全文索引有很大的关系,目前的离线浏览器都是简单的使用数据库查询,一次无法对帖子内容等信息进行查询,大大限制了离线浏览器的用途。
    其实要增加全文索引的功能并不复杂,我也一直都有给离线浏览器加全文索引的想法(虽然我不用),只是Delphi的全文索引库一直没有出现。在去年(前年)的时候我看到了个lucene的Delphi版本,看似会是一个很有前途的东西,却在后来发现这东西居然需要.NET的支持。我对Delphi4.NET一直不待见。在我看来用Delphi对.NET进行封装完全是历史的倒退。接着说Delphi版本的lucene。虽然有4win32的计划,但似乎进展不大。JAVA和.NET都有垃圾收集机制,且JAVA和.NET的语言特性和delphi也有较大的差别,因此需要进行简单的移植难道并不会太小(c版的clucene也有不少问题,但至少算可用的)。
    虽然delphi自己整不了全文索引,但其实还是有不少办法来完成这个这个工作的。前些天我花了一晚上,用java的lucene给现有的离线浏览器加了个全文索引的功能。如果感兴趣就下了玩玩吧。

正文
    不知道现在是否还有人在用离线浏览器,不过即使没人用也没关系,这个程序更多的是演示如何使用混合语言进行开发。

    该版本是在“孟亚永"的离线浏览器基础上进行修改的,MYY的版本又是修改的左大侠的版本的。
    主要增加了全文索引功能(只支持问题)。
    加了全文索引的是主窗口上的快速搜索,将对所有帖子进行搜索(不包括回复)。
    本希望做成支持对回复也进行全文索引的,但这个数据库有些问题,离线浏览器部分不太好改。

  • 数据库的修改
    这个离线浏览器使用的数据库格式和newsmile的数据库有些不太一样,因此在使用前还得先动点手术。
    先执行
    Select ID, DateTime, UserFrom, Content, Parent into LettersReply from letters where Parent<>0
    生成回复表,然后在letters中删除回复信息
    delete from letters where Parent<>0
    再就是将letters的表名修改为lettersQ
    数据库的修改到这里就已经完成了,不过结果这些操作后数据库的个头大了不少,最好使用Access的压缩功能,压缩下。
    数据库修改后,还需要先建立索引,不然全文索引就无法工作,在bin目录下有个make_index.bat,直接运行这个脚本进行索引的创建。建立索引需要花点时间,我对2007的数据建立索引好像花了近10分钟。
  • JAVA部分
    由于全文索引用的是java的lucene,因此需要机器需要安装JDK。
    java部分全文索引的代码里面也带了。
    由于用到lucene,如果需要编译需要去下载个lucene(http://lucene.apache.org/java/docs/)。
  • 关于全文索引
    目前不少开发语言都有全文索引的支持。Delphi也有个,不过很怨念的是需要.NET的支持。
    虽然没有支持native的delphi全文索引库,但还是有些办法给native的delphi增加全文索引的支持的。
    比较容易做的方法有,将C++版本的全文索引库封成activex或DLL,不过我的C++不灵光,所以pass。
    python可以将类直接导出成activex,导出的方法简单。此外网上已经有人这么做了(doindex?)。但我测试pylucene的时候,中文索引通过不了。而且python导出的com需要启动一个com server,所以也pass。
    剩下最简单,最容易处理的方法就是将将全文索引部分写成一个单独的程序。在delphi里直接对这个程序进行调用,并通过获取控制台信息的方式,同索引服务器进行交互。目前采用的就是这个方式。
  • 关于JAVA的个头
    自从MS和SUN翻脸后,windows就不到jre了。要用户去安装一个1xM的JAVA虚拟机实在是一些让人为难。不过JRE还是可以精简到可以忍受的大小的。JRE1.5的虚拟机用7Zip压缩后大小为6xxK。库部分只对需要的部分打包,应当可以将JRE大小控制在2M内(我本来想精简下,不过今天是没时间了)。

使用JAVA在Linux进行串口开发的问题

    使用JAVA进行串口,实在是没啥难度,而且网上已经说的够多的了,因此我也不想多废话。不过其中有个问题实在是诡异(在Linux下)。
    虽然代码看上去没啥问题,但每当执行setSerialPortParams就抛出异常。
Detected: /dev/ttyM0 java.io.IOException: Not all params are supported by kernel
        at com.sun.comm.LinuxSerial.nativeSetSerialPortParams(Native Method)
    本以为是我 哪里搞错了,到网上一看才发现不少人遇到了和和同样的问题。问题的解决方案也是千奇百怪。有人说调用setSerialPortParams这个函数前要先sleep(10),有人说要先println。我加了print依旧失败,再往下看,有人说将setSerialPortParams这个函数放到try模块里就可以。加完try后再测试还真的好了。目前暂时只能将这个问题定义为“诡异”了。

Delphi的“BUG”

    其实不算是Delphi的BUG了,但真的是非常非常讨厌的一个特性。
    我本以为为初始化过的类就应当是nil。所以使用Assigned判断类变量是否初始化过。那知道我是否初始化过都能通过nil的检测。据说Delphi为了保证类函数的使用,会自动对这个类变量进行初始化。而当前类的指针就随便指向了一块内存空间。
    感觉这个问题实在是太讨厌了,大大增加了编码出错的概率。一个变量如果并不是需要在创建的时候初始化的你就无法通过判断是否为nil检测该变量是否初始化过,除非你在创建的时候就手动赋值为nil,但这点很容易被忽略掉。

PS:
    今天又和同学讨论了下这个问题。想来这个问题也是可以理解的,在C++中也存在类似的问题。看来我是被JAVA等高级语言给惯坏了。nil这个初始值虽然很简单,但确实很有用。

最近为Delphi吐血超过一公升

虽然这是一些牢骚,不过和编程还是多少有些关系的,先放这里吧。

    虽不敢称对Delphi有多精通,但自信对Delphi的熟悉程度绝对超过绝大多少的Delphi的开发人员。不过最近实在是吐血,大口大口的吐,血如泉涌。粗略估计绝对吐血量绝对超过一公升。按我的说法,最近真是将数年来未遇的问题都全部给遇了个遍。这些问题搜遍地了互联网,能找到的除了问题还是问题。最的的感觉是,某些和系统结合紧密的东西还是用VC吧,毕竟都是老比家的。    
    那些小吐的就不说了,这里只列举些失血过度的。
    最先遇到的是类似WORD的多窗口程序问题(一个程序的各个窗体都在任务栏上显示一个按钮)。其实这个问题以前也遇到过,而且网上也有不少人遇到。但这问题一只就没有过一个好的解决方案。Delphi做多窗口程序最大的问题就是,不能使用模态窗口,模态窗口很容易跑到主窗口后面,这时候就是死都出不来了,这能动用任务管理器。由于这个问题涉及到Delphi的VCL体系因此很难解决。
    为了这个问题,有将互联网翻了个遍。网上应用的信息实在是太少了。我将能找到的一切方法都试了个遍,甚至连hack Delphi的方法都用过了,依旧是无疾而终。真是整到让人绝望。不过好在问题最终解决了,虽然解决方式不太优雅(应当说是,实在是太uglily了),但至少算是解决了。
    然后IE插件的右键菜单问题。由于Delphi的UI并不是线程安全的,导致IE插件的右键菜单只能在当前窗口弹出,通过URL打开的新IE窗口无法弹出右键菜单。这个还好点,在网上至少还恩能找到解决方案。网上说方案有两个一个是使用API,另外一个使用线程安全的第三方控件easymenu。由于不习惯使用API(而且还不知道用API是否会带来更多的其他问题),于是先找了easymenu测试了下。死得更惨,直接挂掉。API还好,可以正常工作,不过太过繁琐。于是尝试对Delphi的控件进行扩至,可是发现根本就无法实现要求。还好,这个问题最终也算是解决了,使用的方法依旧比较无耻。
    再下面的这个问题我就实在是无能为力了,血流不止。Delphi的IE插件弹出的窗口并没有使用XP的界面风格。如果是应用程序这倒好处理,放个控件就可以,但IE插件就是不行。又是放狗(google)又是划船(baidu)的,找到的都是一些鸡毛蒜皮的东西。还拉了个兄弟帮忙,结果一同被郁闷。真的让人怀疑这世界上是否真的存在这么一样东西。(后记:就在我要吐血身亡的前一秒,终于让我找到解决方案了。EmbeddedWB里面有一个XP风格支持的Demo)
    就这些东西还不算,公司东西出的问题也是让人血流不止。
    公司用Delphi给星空极速做了个插件,看上去好好的,也可以正常的加载。但只要程序的焦点落到这个插件里,等再移开的时候程序就挂死了。即使是最简单的ActiveForm上放一个Edit也挂。用VC写了个简单的测试程序,问题依旧。用spy++,发现按在TabControl出现消息的死循环。去掉TabControl再尝试,发现OK了。本以为将TabControl全部换成TPanel就万事大吉了。那知道测试程序好了,星空急速里还是老样子。这下更惨,以前出现消息循环的地方是在插件里,这下在星空急速里就出现消息循环了,消息根本就没有传递到插件里。死得不明不白的。再次绝望。
    如果你想尝试吐血的滋味,使用Delphi写个Activex的插件吧。保证你爽到极点。

后记:
    星空极速的问题终于也被我给搞定了。给我的感觉是似乎没有什么问题是解决不了的,不过吐血已经吐得够多的了,且如果有时间我似乎应当关注些其他东西了。

Django很可能存在性能问题

前言
使用Django开发WEB2.0的同学注意了,Django很可能存在性能问题,而且是灾难性的。(和算命先生一样,先吓唬吓唬人,危言耸听)

问题
WEB2.0提倡的是用户交互,因此WEB2.0站点不可能和传统站点一样,将大部分的页面都静态化。在频繁的交互中,数据库的访问必不可少。但Django的O/R
Map实在让人没底。
Django的O/R Map使用方便,但基本是个黑盒,难以进行优化。也许有人说优化是以后的事。但很多时候在最开始没有留下优化的余地,到真正需要优化的时候将苦不堪言。
对数据库的优化主要有减少数据库的访问和sql优化。将少数据库的访问可以通过cache等方式实现,这部分应当都一样,没有太多可以讨论的。对于SQL的优化,Django的O/R
Map实在封得太多,似乎也不存在太多优化余地,只能将O/R Map换成SQL。
但O/R Map在一定程度上是一种设计思想,将一个已经上线的O/R Map换成SQL并不会是一件很轻松的事。
分表也是常用的数据库优化方式,像Hibernate还可以使用Native Sql实现对分表的支持,但Django就不行。这时候有得换成Sql。
等改完后,原先优美的代码都已经变得惨不忍睹了。

相关数据
Django的应用中一直没有出现过什么大流量的网站。Django的普及程度可以说明一定问题,但或许Django本身就不适合做这个。
由于我并没有什么大流量的django站点,因此我的数据只能从网上找了。PS:我的小站,使用的是Bluehost主机中最便宜的一款,虽然没什么流量,但我进管理平台的时候几乎100%的500错误。

网站名称       使用技术                    Alexa排名/收录量/PageView  服务器
Delphi盒子    ASP/SQLServer           21.05w  /3.57w/3w           1G RAM
好看簿         Django                      16.9w    /7.05w/NA           3服务器
JavaEye      ROR                          2w        /24.6w/15w          4G RAM
豆瓣(2006数据Quixote                   NA        /NA    /30w          NA

备注:
好看簿
虽然具体流量不清楚,但参考Alexa的排名,流量应当在10w以下。
这个最早是有木头那听来的,知道是Django做的。今天在网上看到好看簿的介绍,说换了3台服务器。
对于创业期的网站来说,如果不是处于性能原有,应当不会如此奢侈。
因此猜测在单服务器时候,负载已经不太低了。

Delphi盒子
这个不属于WEB2.0页面交互比较少,因此数据库访问应当不会太过频繁。
仅仅做参考。

JavaEye
这个大家应当都比较熟悉。关于JavaEye的流量站长大人自己说得最清楚了。
HP DL145 G1,两路AMD Operton 2GHz CPU, 4G DDR RAM, 73G SCSI 15k Disk
Linux Kernel-2.6.7,lighttpd-1.4.13,MySQL-5.0,ruby-1.8.4(GC patch)
由于网站的访问量大部分集中在早上9.00到晚上9.00这12个小时的范围内。因此可以大致粗略的认为12小时处理12万动态请求,平均每小时处理1万动态请求,也就是说平均每秒处理3个动态请求。
服务器的平均CPU使用率在繁忙的时候,大概15%左右,MySQL数据库繁忙的时候平均每秒发送超过100条SQL语句,24小时平均每秒发送45条SQL语句。硬盘IO非常少

豆瓣
WEB2.0的代表,通是使用python开发。阿北在豆瓣的早期有谈论过豆瓣的性能问题。
现在cpu使用15%左右。每天30万页访问(白天每秒10次的样子),100%是动态页面。服务器的访问响应时间平均仍在0.05秒以下。
加上所有的封面照片,是有几十个G。不过这些不在数据库里。数据库现在有5G, 最多的是书的信息(40多万条)和用户收藏和评价(50多万条)。这个不包括冗余。
mysql用了innodb和myiam. 读/写频繁的用innodb, 读多写少、写多读少(比如log)或者需要full text
index的用myiam. replication/cluster还没有,不过很快会有。现在每晚用mysqldump做backup.

后记
    主要是这两天看了些Scaling(可伸缩?)方面的东西。感觉Django的O/R Map的功能难以支撑Scaling。当然,对于我来说这些东西应当都不是问题,至少暂时不会是问题,还没机会遇到这些问题。
    在很多时候性能问题很可能是给伪命题。对于大多数网站来说很可能根本没机会遇到性能问题。类似Django/ROR等快速开发框架的好处是可以让你快速实现你的想法,给你一个演进的机会。如果真有机会遇到性能问题,那也是一个挺不错的事情(网站发展到一定规模)。