SQLObject的问题

提到Python的ORM,首先想到的有两个SQLObjectSqlAlchemy,还有Django的ORM,另外,还有Zope的。

前几日和Nicholas又讨论到SQLObject这个东西,就目前Python现有的ORM工具来说,最容易使用还是它了,SqlAlchemy对于懒人、初学者的我来说,还是复杂了点;而Zope相对是个庞然大物,整体的解决方案,小东西往往也不会去用到。

当然SQLObject的问题不在于它使用了ActiveRecord模式,Django的ORM同样也用到了这个模式,因为起初用TurboGears(0.8.9,当时SO的版本可能还没到0.7)做了一个小东西,那个时候便发现了诸多问题,尤其在编码问题上卡住了。这一次正准备对原有的东西增加新的功能,便几乎无法做下去了。

比如业务领域有“角色”这个词,在业务上应当翻译成“Character”。我建立了一个Character类,SO在自动根据代码的Model建立表结构的时候,不会像Rails那样考虑单复数,因此它会尝试建立“character”表,而Character、Char在mysql中都是保留词,而SQLObject甚至都不知道在SQL语句中对其进行转义。为了解决这个问题,我指定SO去建立characters表,接下来的问题就是,SO在寻找Character表相关的外键时,是考虑了characters_id,而对于存在这个外键的表,SO在建表的时候还是使用了character_id这个名字,最终导致了错误。

另外编码又有新问题,Python中使用%格式化操作符时,左边或右边任意一方出现了unicode字符串,最后的结果都会是unicode,而SO也同样没有考虑到,最后导致本已经是unicode的查询字符串,SO还要去再decode一次,最后导致了错误。

所以不推荐大家使用SO,尤其要做复杂产品的时候。

另外,Django的ORM也可以拿出来单独使用,值得研究一下。

Ubuntu硬盘ISO安装一法

我在公司的机器没有光驱,有Ubuntu的Desktop安装盘也没有用,捣鼓了很久的硬盘安装也没有成功,因为Ubuntu Dapper使用了Live CD的启动方式。而我尝试过唯一能从硬盘ISO安装成功的就是Fedora Core 5了。
在研究了数周毫无结果就要放弃的时候,我突然灵机一动,觉得既然Ubuntu Dapper的CD就是一个完整的Linux系统,那何不直接拿来用呢?在经过了一整夜的研究之后,我终于用这种丑陋的方法,将Ubuntu Dapper装在了没有光驱的机器上。
具体步骤如下:

  1. 进入原有的Linux系统,先对系统进行分区,将目标系统的root分区准备好,并挂载在某个目录比如/target下,然后将其他分区准备好,相应挂载在/target下(比如/usr, /var, /home等)。在此不赘述,可以参考Gentoo磁盘准备的教程
  2. 使用

    mount -o loop -t iso9660 [ISO文件路径] [挂载路径A]

    将镜像挂载到某个目录下A,这里我使用的镜像是Ubuntu Dapper的desktop安装镜像。

  3. 然后再用

    mount -o loop -t squashfs A/casper/filesystem.squashfs [挂载目录B]

    ,因为Ubuntu Dapper的Live CD的文件系统内容都是以squashfs形式压缩在光盘的casper/filesystem.squashfs文件中的。

  4. 在刚刚挂载好的Live CD的目录B中,复制所有文件到/target下,

    cp -p -r B/* -t /target

    其中-p表示保留所有的文件权限信息,-r表示递归复制。这时候基本的系统内容就有了

  5. 如果有chroot,也可以调用:

    chroot /target /bin/bash

    (以下假设运行了这条指令,根目录转到了/target中)

  6. 准备/etc/fstab,起初的内容都是空的,根据自己分区的情况酌情编写,以下是一个参考例子:

  7. 准备引导文件,如果已经装了Grub或者Lilo,只需要修改一下相应的配置文件,比如,在grub的menu.lst中加入:

    title Load Ubuntu Dapper
    root (hd0,5) #假设是这里的安装根目录
    kernel /vmlinuz root=/dev/hda6 quite splash –
    initrd /initrd.img

  8. 如果是自己用无所谓建立新用户的话,将来可以直接使用root(初始密码为空),但必须在/etc/X11/gdm中,将gdm.conf和factory-gdm.conf中的AllowRoot设置为true。如果需要更加安全,则请建立相应的用户,但必须在/etc/sudoers中添加相应的用户,使用visudo来进行编辑。
  9. 编辑/etc/apt/source.list,添加一些ubuntu的apt源,具体就不列出来了。
  10. 调用dpkg-reconfigure -a对所有安装了的Debian包进行重新配置,尤其重要的是xserver-xorg和语言等等
  11. 之后重启,便可选择进入我们克隆出来的Live CD的系统了。这时候应该对系统进行一些设置,比如在系统中选择自己的语言,并使用新立得来更新系统,同时也可以将Ubuntu Live CD相关的一些包删除。
  12. 这时候,终于可以在机器上使用Ubuntu Dapper了。

唉……瞎折腾啊。

Python MySQLdb的重大疑问

最近开发Python,数据库操作一直用的是SQLObject,但有个问题很让我头疼,就是MySQL的数据库的编码问题,主要是MySQL的。
起初我现在我在SQLite上测试开发,并没有出现问题。SQLObject的UnicodeCol工作很正常。而同时起初数据库中并没有任何非ASCII字符(也就是全英文),而后需求变化,增加了欧洲的一些内容,就涉及到latin1编码了,但奇怪的是,只要超出ascii范围(比如中文),即便通过Python将其转化为Unicode或者UTF-8编码的str(使用decode和encode方法),SQLObject在插入的时候就会出错。后来经过反复的检查,是MySQLdb的一个问题,SQLObject会通过获取数据库链接的character_set_name(),取得链接的字符集,然后对查询进行编码以符合这个字符集,但据调试,无论我用什么方法,比如链接的set_character_set()方法、执行“SET NAMES UTF8”这个语句,character_set_name()都总是返回“latin1”,这些可苦了我了,不知道这是不是算一个Bug。

时间悖论

一直想写篇关于时间的帖子,无奈本人数学功底太差,对于几位大科学家的理论几乎根本无法理解,不过,还是要在此讨论一下自己的看法。

当大家谈到时间旅行(主要指回到过去)的时候,都会提到一个著名的悖论——一个人回到过去,将其父亲/母亲/祖先杀了,那么他从哪里冒出来的呢,他又算什么“东西” 呢?这个逻辑上的矛盾一直困扰着大家,记得看到书上说,霍金认为,宇宙会在对这种动作有某种程度上保护,阻止这种行为的发生。我渐渐觉得,在时间旅行的问题上深入的越久,人就越容易陷入现在认为错误的“宿命论”的泥潭中。

首先,并不一定是这类回到过去的行为是一种悖论,只要是想回到过去,其实都是为了产生这种悖论的。为什么呢?你只要问问自己,如果你能回到过去,你会去做什么事情——肯定会是一些你一直后悔的事情。比如某个人的亲人死了,所以他要回到过去,去救他的亲人,但他如果成功了,那么过去的那个他再度到现在这个时候,他就无须再次回到过去了,因为他亲人没死。再比如,机器猫上的大雄,考试没及格,坐时间机器回到考试前一天,将答案告诉过去的他,那么过去的那个他如果考试通过了,那么考试过后,就无须再回到过去完成这个“使命”。还有,周杰伦唱的那个“就回到过去,试着让故事继续……”,但若是故事按照他所期望的发展下去,那他还要这样去后悔么?

所以,要么是这种逻辑在时间的问题上不适用,要么就是,想回到过去改变过去,是不可能成功的,既然不可能成功,那么,这就是一种“宿命”。

其实还可以有另一种考虑方法,如果你回到过去了,帮助了过去的你,那么过去的你的记忆中应该知道你回去过了,而且,你知道将来的某个时刻,你还会像当时一样回去,去完成你的“使命”,这又陷入了宿命的怪圈中。

所以,我也认为,现在单纯的单向的时间旅行是不存在的,也就是说,未来的某个时刻的人,单方面要回到过去,只能是一厢情愿,必须要靠过去的那个时刻的人的共鸣,或者召唤,两个时间点上一起产生作用,才能打开时间的隧道。
另外,还有一个矛盾,就是和广义能量守恒定理之间的矛盾。它基本理论是这么说的:

“物理学宇宙(简称宇宙)是由多种形式的能量组成的,或者说宇宙的本质就是能量(广义)或物质(广义),各种能量形式可以相互转化而总量守恒。”

但如果有了时间旅行,那未来的时间来的物质,能回到过去,但这些物质回去了就不走了的话,那么这个定律就不适用了,可以需要在更广义的条件下进行定义。
还有就是那个很著名的一个人的故事,也是关于时间悖论的:

一九四五年的一天,克力富兰的孤儿院里出现了一个神秘的女婴,没有人知道她的父母是谁。她孤独地长大,没有任何人与她来往。

  直到一九六三年的一天,她莫明其妙地爱上了一个流浪汉,情况才变得好起来。可是好景不长,不幸事件一个接一个的发生。首先,当她发现自己怀上了流浪汉的小孩时,流浪汉却突然失踪了。其次,她在医院生小孩时,医生发现她是双性人,也就是说她同时具有男女性器官。为了挽救她的生命,医院给她做了变性手术,她变成了他。最不幸的是,她刚刚生下的小女孩又被一个神秘的人给绑走了。这一连串的打击使他从此一蹶不振,最后流落到街头变成了一个无家可归的流浪汉直到… …

  一九七八年的一天,他醉熏熏地走进了一个小酒吧,把他一身不幸的遭遇告诉了一个比他年长的酒吧伙计。酒吧伙计很同情他,主动提出帮他找到那个使‘他’怀孕而又失踪的流浪汉。唯一的条件是他必须参加伙计他们的‘时间旅行特种部队’

  他们一起进了‘时间飞车 ’。飞车回到六三年时,伙计把流浪汉放了出去。流浪汉莫明其妙地爱上了一个孤儿院长大的姑娘,并使她怀了孕。伙计又乘‘时间飞车’前行九个多月,到医院抢走了刚刚出生的小女婴,并用‘时间飞车’把女婴带回到一九四五年,悄悄地把她放在克力富兰的一个孤儿院里。然后再把稀里糊涂的流浪汉向前带到了一九八五年,并且让他加入了他们的‘时间旅行特种部队’ 。

  流浪汉有了正式工作以后,生活走上了正轨。并逐渐地在特种部队里混到了相当不错的地位。有一次,为了完成一个特殊任务,上级派他飞回一九七零年,化装成酒吧伙计去拉一个流浪汉加入他们的特种部队。

这个逻辑相当混乱的故事中,只有一个人,其实,仔细分析,就会发现,那个特种部队中,其实他的上级就是这个人,而部队中所有人都是这个人,这个人在这种逻辑混乱中,不断通过时间悖论来复制自己,有点像那个黑客帝国中的特工Smith吧,算是宇宙这个大Matrix中的病毒吧。不知道这里面能量是否守恒。

还有关于时间裂缝,就是说某些人一直生活在某两个时间点之间,他过完了这段时间后,就重新回到起点,再过这个时间,永远没有尽头。奇怪的是,一,他是如何进入到这个时间裂缝中的,二,如果他知道自己陷入了时间裂缝,为什么不能从中跳出来呢?因为不可抗拒的“宿命”?在一瞬间时间无限制地叠加在他的身上?从无中诞生,最后又归于“无”。

写到这儿,差不多把我所知道的一些疑惑都列举出来了,不知道人类还有多久的时间,能去解决这些问题,不过,如果人都不死的话,谁去管这些事情呢,呵呵。

给VMWare的虚拟机启用3D加速

  1. 虚拟机选择Windows 2000或者XP guest操作系统。注意:不要对已经启动或者被挂起的虚拟机启用Direct3D。
  2. 给配置文件(.vmx)添加一下内容:
    mks.enable3d = TRUE
    这一行将启用宿主的3D加速。不仅对于寄宿机支持3D加速是必要的,同时也可以让宿主对寄宿机的显示区域启用2D加速。
  3. 你可能还需要加入以下几行:
    svga.vramSize = 67108864
    这一行将虚拟显卡的VRAM量增加到64MB。增加VRAM有助于减少寄宿机的延时。最大值为128MB。
    vmmouse.present = FALSE
    这一行将禁用寄宿机中的绝对定位设备。需要用到DirectInput相对模式的应用需要将寄宿机的绝对定位设备关闭。实际操作中,这只针对一些全屏的3D应用(例如,像第一人称射击之类的实时游戏)。注意:如果你设置了vmmouse.present选项,你还需要关闭Preference设置对话框中的Input标签页中的motion ungrabbing(移动时释放鼠标捕获)设置。
    若要为vmmouse.present关闭释放捕获,请按以下步骤:
    a. 选择 Edit > Preferences.
    b. 点击 Input.
    c. 取消 Ungrab when cursor leaves window.

The Vision

看了Nicholas的这篇梦的记录,我也想写一下,这是好几天前做的梦了,但是还是要写一下。那简直就是好莱坞大型科幻片。大致的内容是:
某种 未知的力量——可能是外星人,也可能是神——将美国的太平洋舰队传送到了俄罗斯的军事港口,而把俄罗斯的舰队传送到了美国的军事港口,我当时站在俄罗斯的 港口(也可能是中国某港口)附近的大楼上,看着成群的舰队莫名地凭空出现,巨型的航母、舰队在眼前慕为壮观,而当了解了那是美国的舰队之后,感到了无名的 恐惧,然后可想而知,不知是哪一方先开火,整个港口乱成一团,双方猛烈的攻击着,甚至一些舰船直接冲到了岸上。而我便和大家一起,沿着一个圆形的楼梯一直 往下一直往下走,逃往一个地下的区域——似乎,这已经是世界末日了…………
这是一个,还有另一个则很有生活情调,我走在马路上,应该是类似西方电 影中常出现的那种小路,路两旁是很高的白色栅栏,人行道上或有一些小树。我走到了一个商店门口,商店前有较长的台阶——目测门离马路约20米,高2米,商 店门面类似于肯德基,左边是门,右边整块都是玻璃,我可以透过玻璃看到里面有一些小资妇女在吃着一些甜点,她们应该是坐在沙发上——也是类似于肯德基那种 和墙壁合在一起的沙发。于是我也走进去,问服务生要东西吃,她说,这些点心都是免费的,随意吃,于是乎,我就坐在那边的沙发上吃了起来,而后,有人(一男 一女,男的很瘦,很高,女的则约是中年)请我去这个店内庭去吃东西,里面起初十分狭小,而后我们吃了点东西,进入了一个十分旷阔的类似于体育馆的地方,而 我觉得,更像是没人的火车站,而这里面却有一些小孩玩的那种小型游乐场(肯德基、麦当劳那种)。
我并不清楚这些意味着什么,不过,记录自己的梦境,却是一件很有意思的事情。

Squid 2.6配置的注意事项

前一阶段Squid推出了2.6版,在缓存机制上有了更好的统一,将反向代理和正向代理统一在了一起,但是也有一些问题。
第一是反向代理配置方式改变了,去掉了httpd_accel_*这些配置,而改用http_port和cache_peer等配置来完成,例如:

有了这两条,就可以实现反向代理了
第二如果Apache有身份验证的话,Squid 2.6可能并不会将Authorization的HTTP头发送给Apache,所以我在Squid 2.6后配置Apache + Subversion就无法使用身份验证——这个目前还没办法解决。
第三是Squid 2.6的基于IP的反向代理服务器的配置改变,也就是Squid 2.5中的httpd_accel_host virtual,在Squid 2.6的方法是命名多个parent、originserver的cache_peer,然后配合cache_peer_domain来指定对不同域名发送到不同的上游服务器;

需要注意的是,每个cache_peer都必须至少有一个cache_peer_domain分配到其上,才能真正实现类似virtual的配置。

Cache_Lite的检测缓存失效

PEAR组件Cache_Lite是一个很实用的文件缓存组件,我在PHP编程中常常用到,现在我常需要检测某个id的缓存是否已经失效了,而Cache_Lite本身并未提供这样的功能,因此我写了这样一个函数:

使用也很简单,应该一眼就能看明白。当然也可以通过继承Cache_Lite,并添加一个方法来完成。

Currying的翻译

函数Currying,是我所一直不能确定的英文翻译之一 ,另外还有一个Web的翻译。

函数Currying的意思就是将参数和函数关联起来,变成一个新的函数。比如一个二元参数f a b

当给出f 1的时候,应该返回什么呢?一般的语言中,要么是将b设为一个默认值,要么就是直接出错,而当有了Currying,那么f
1其实返回一个函数g x = f 1 x。
当然这个描述也不够好。

其实其命名是为了纪念一个逻辑学家 Haskell Curry 的――函数式语言Haskell也是为纪念这个人,当然这个东西并不是他第一个发现。

既然作为姓名,数学中可能不会进行翻译,就叫做Curry化,或者柯里化,不知道还有什么更好的翻译方法,能较为直接地体现其真正的含义。

给“Web”一个准确的翻译

一般提到“web”这个词,大家都知道它是“网”的意思,而且还是“蜘蛛网”。在it界,大家一般都知道是“网络”的意思,但是很奇怪的是,“net”也一样是“网”,同样表示“网络”的意思,这就很奇怪了。到底两者应该如何翻译?

我查了金山词霸,web的定义是:

n. 环球网
n. 网, 蛛丝, 蹼, 翼手, 织物, 圈套, 卷筒纸

而net的定义是:

n. 网, 网络, 网状物, 净利, 实价

而且在计算机中,一般等同于network这个词:

n. 网络, 网状物, 广播网

而如今在国内,始终没有办法很好地区分这两个词,而往往涉及到web的时候,都会忽略不翻译,比如web appliaction,一般不会翻译成网络应用,而是说成web应用,web service,也往往翻译成web服务,而不是网络服务。web 2.0更没有人去翻译它了,绝不会看到有人说成是“网络2.0”。为什么不翻译,就是因为net和web有区别,但直接翻译过来,比如web service,是一种软件技术,但说网络服务,很多人会和network service,也就是诸如拨号上网、宽带之类的相混淆。

在学校上课的时候,学过几门和网络有关的课,比如“网络工程基础”,“网络编程基础”等课,回忆一下其中讲过的tcp/ip的协议栈,里面是这么讲的:

  1. 应用层
  2. 传输层
  3. 互连层
  4. 网络接口层

而我记得很清楚,网络工程中,基本没有涉及到很多应用层的东西,网络编程基础,一般教授的是传输层的编程,至于应用层,也仅仅教授了应用层很底层的知识。

再考虑网络工程这个词,英文是network engineering,而网络工程考虑的问题多数是硬件、如何组网,可以说这些是互联网比较底层、基础的东西。

反观web 2.0的定义,可以发现,其中多数是有关最终用户的内容,是直接和人打交道的。
我们现在就可以下结论了,net是我们最宽泛的“网络”概念的底层基础,而web则是指顶层的应用,甚至包含了人与人利用web进行的交互。

概念区分清楚了,那么如何给web一个准确的翻译,金山词霸给出的“环球网”读起来也不是很顺口,我现在也没有什么十分好的答案,希望大家能给我出个主意。