Archive for September 10th, 2007

Firebird笔记

Monday, September 10th, 2007

Firebird笔记

目录

1   选用理由

我正在开发一个爬虫,原来使用的SQLite数据库的多线程并发操作很麻烦,我一直都没能找到比较好的方法来避免数据库锁定,所以在尝试了一个多月之后我最终放弃了。放弃之后使用了BerkeleyDB作为数据库,自己写接口。运行过程尽管还算很快,但是也有问题,就是多线程操作BerkeleyDB时会让Python解释器出现段错误而退出,这也是无法忍受的错误。

所以在权衡之后我最终还是决定捡起一度放弃的Firebird数据库。决定未来将其集成到我的爬虫当中。另外,我的另外一个产品也需要使用足够健壮的数据库服务器。

关于MySQL,我还是很信赖其稳定性的,使用感受也不错,但是在我的程序中并不需要复杂的权限控制,而且通过网络连接数据库的安全性和速度也让我很讨厌。所以选用了Firebird的嵌入式版本。

2   与Python的结合使用

Firebird的Python接口叫做KinterbasDB,支持所有版本的Firebird和部分版本的Interbase。尽管支持,但是对1.0、1.5、2.0版本的Firebird是使用不同的安装包来支持的。

在Windows 2000系统之下我使用了 kinterbasdb-3.2.win32-FB-2.0-py2.4.exe 来进行安装,版本为3.2,对应Firebird版本为2.0。双击然后一路继续就完成了。

3   安装Firebird的嵌入式版本

因为考虑到未来程序的可移植性,所以我坚决避免使用Firebird的安装包进行安装。在安装完成 KinterbasDB 之后尝试在Python中导入:

>>> import kinterbasdb

发生了错误,提示找不到DLL文件,然后我使用了压缩包 Firebird-2.0.0.12748-0_embed_win32.zip 。对缺少的DLL文件依次从压缩包中解压出来并放置到目录 C:Python24Libsite-packageskinterbasdb 目录中。因为我发现这个目录是可以被路径识别的,并且跟 KinterbasDB 的关系密切。如下几个文件是导入语句所必须的:

  • fbclient.dll :最初叫做 fbembeb.dll 需要复制过来以后该名为新名字的,否则 KinterbasDB 是不认的。
  • icuuc30.dll :不知道干什么的,反正必须要有。
  • icudt30.dll :不知道干什么的。
  • icuin30.dll :不知道干什么的。

这四个动态链接库的大小就已经达到了 3.68MB ,不过面前还是可以接受的。

在这样一番折腾之后就可以成功的导入了,做了一下dir,结果超长,此处也就略掉吧。FB支持的功能非常多,包括触发器、事务、存储过程之类的,这些东西在开源数据库当中是非常少有的。

4   《Firebird嵌入版本开发方案》笔记

Firebird的官方网站( http://www.ibphoenix.com )。这里还推荐了一个叫UIB的东西,网站是( http://www.progdigy.com/UIB/ )。原来用于Interbase的可视化管理工具IBExpert ( http://www.ibexpert.com )从某种程度上来说也可以用于Firebird。

拒作者说IBExpert好像是有限制的,所以推荐去 ftp://hdkej.8800.org 下载一个修改过的版本,没有限制。运行IBExpert新建数据库时服务器选择Local,Client Library选择fbclient.dll。

看来UIB是给Delphi使用的一套接口,Python的就免了。作者的调试过程发现不能让两个进程同时访问数据库。

5   博客 http://tb.blog.csdn.net 的Firebird使用 笔记

推荐下载IBExpert而已,另外就是FB内置了isql.exe在控制台进行数据库的基本操作。

6   《python2.4 连接firebird1.5 一个连接数据库的文件》笔记

作者使用Python2.4和KinterbasDB连接了FB数据库。首先是导入:

import kinterbasdb as kdb

初始化连接并返回连接对象:

conn=kdb.connect(dsn='lq:D:\\data\\aaa.FDB',user='sysdba',password='masterkey')
conn.text_factory=str

连接选项的dsn用来指定数据源,用户名密码sysdba:masterkey是默认的。第二行是用来避免 “Could not decode to UTF-8 column” 错误的。

因为很多时候程序需要随身携带数据库,所以需要使用相对路径,文中给出了获取当前路径的方法:

import os
ypath=os.path.abspath(os.path.dirname(sys.argv[0]))

如果需要通过列名来返回值,则可以作如下设置:

conn.row_factory=kdb.Row

通过ConfigParser模块支持INI格式的配置文件,如下是某配置文件:

[SQLFbDB]
dbname=data\aaa.FDB

如下是处理配置文件的代码:

import ConfigParser
config=ConfirParser.ConfigParser()
config.read('config.txt')
dbname=config.get('SQLFbDB','dbname')

7   《本地数据源:使用firebird数据库》笔记

Windows下的Firebird有classical和superserver两种版本。配置文件aliases.conf配置数据库别名,firebird.conf配置数据库参数如rootpath。

嵌入的FB数据库不再支持多用户访问和用户安全控制,不过对于本机程序来说很正常。

在.net下使用时有个连接选项叫server type,需要设置为1才是嵌入FB数据库。

8   Python-Chinese邮件列表上朋友的回复

  1. 安装KInterbasDB,会产生一个 lib\site-package\kinterbasdb 目录。

  2. 在kinterbasdb目录下新建一个embedded目录,然后将嵌入式的Firebird中的 fbembed.dllfirebird.msgib_util.dll 这3个文件放入embedded目录下。如果需要国际化支持,则同时复制intl子目录,这个目录包含 fbintl.dll 文件。

  3. fbembed.dll 文件改名为 fbclient.dll

  4. 这时就可以使用FB数据库了。

  5. KInterbasDB为了向后兼容,默认使用 mx.DateTime 模块,但是在Python2.4下并不需要而且多余。在Python标准库中的datetime模块更好用。需要用datetime替代mx.DateTime则按照如下修改:

    import kinterbasdb
    kinterbasdb.init(type_conv=200)

实际测试发现如果把几个动态链接库放在 embedded 目录中,则会提示动态链接库找不到。

使用twisted.python.log日志

Monday, September 10th, 2007

使用twisted.python.log日志

目录

版本: 2.4.0

1   简单使用

Twisted提供了一个简单而且可移植的日志系统叫做 twisted.python.log 。它包含3个函数:

msg

记录一条信息,例如:

from twisted.python import log
log.msg("hello, world")

err

把错误写入日志,包括traceback信息。你可以传递一个 failure 或者异常的实例,甚至什么都没有。如果传递其他的东西则会通过 repr() 函数获得字符串来显示。如果什么都不传递则会自动构造一个 Failure 实例,一般用于 except 子句:

try:
    x=1/0
except:
    log.err() #会自动记录ZeroDivisionError

startLogging

通过一个类似文件对象来开始日志,例如:

log.startLogging(open("/var/log/foo.log",'w'))

或者:

log.startLogging(sys.stdout)

缺省条件下,startLogging会同时将输出重定向到sys.stdout和sys.stderr。你可以在startLogging中设置setStdout=False来禁用这个功能。

1.1   日志与twistd

如果你使用twistd来运行你的程序作为后台进程,则他会自动托管startLogging,甚至还会自动轮训日志。查看 twistd and tac 一节或twistd的man手册了解更多。

1.2   日志文件

twisted.python.logfile 模块提供了一些可以同startLogging共同使用的类,例如 DailyLogFile ,提供了以天为单位的日志轮询。

2   编写日志监视器

日志监视器是Twisted日志系统的基础。一个日志监视器的例子是供startLogging使用的 FileLogObserver ,可以把事件写入文件中。一个日志监视器是可调用的,并且只接受一次字典作为参数。随后你可以用它来接收所有的日志事件(当然也会给其他日志监视器):

twisted.python.log.addObserver(yourCallable)

字典至少有2个项目:

message

日志信息,一个列表或字符串,被log.msg或log.err传递过来的。

isError

一个布尔值,如果为True时就是从log.err过来的。如果为True说明字典当中还会有个Failure对象。

其他项目是自动被加入的:

printed

这条信息是从sys.stdout中捕获的,例如这条信息是从print输出的。如果isError同样为True,则是从sys.stderr来的。

你可以通过 log.msg 或 log.err 传递附加项目到事件字典。标准的日志监视器将会忽略他们不用的字典参数。

Note

注意

  • 不要在日志监视器中抛出异常,否则会挂掉。
  • 不要在日志监视器中阻塞,尤其是在主线程中。这将会导致很多问题。
  • 日志监视器需要线程安全。

Erlang超快速入门

Monday, September 10th, 2007

Erlang超快速入门

日期: 2007-04-06

目录

1 开始使用erlang

如果你在unix系统下输入 erl ,或者在Window$系统下双击Erlang的图标,你可以看到一些提示:

os prompt > erl
Eshell V5.5.4  (abort with ^G)
1> _

其中 “>”提示符意味着系统正在等待输入。

2 使用Erlang作为计算器

1> 213183682167*12937192739173917823.
27579983733990928813319999135233
2> _

记住每个表达式以英文句号结束

3 编辑前面的表达式

可以使用简单的emacs命令获取前面的表达式。常见的几个如下:

Unix键 Win$键 说明
^P Up 获取前一行(previous)
^N Down 获取下一行(next)
^A Home 到行首
^E End 到行尾
^D Del 删除光标前字符
^F Left 向前移动一个字符
^B Right 向后移动一个字符
Return Enter 执行当前命令

注意:^X意味着Control+X 。

尝试按下Control+P来查看结果。

译者注:一位朋友提示如上的快捷键是在unix系统之下的,Window$下的快捷键附在了如上列表后的括号内。另外,在Unix系统下使用Control+G的退出方式,在Window$下使用Control+C来退出。

4 编译你的第一个程序

把如下内容输入到一个文件里:

-module(test).
-export([fac/1]).

fac(0) -> 1;
fac(N) -> N * fac(N-1).

把这些存储到文件 test.erl 中,文件名必须与模块名相同。

编译这个程序使用如下命令,并且运行:

3> c(test).
{ok,test}
30> test:fac(20).
2432902008176640000
4> test:fac(40).
815915283247897734345611269596115894272000000000
32> _

现在可以做些其他有趣的事情了。

5 深入了解Erlang

Getting Started

Warp me to the documentation – I want to read it all

memcached简介

Monday, September 10th, 2007

memcached简介

翻译: gashero

目录

主要取自 memcached 的主页。

memcached的Python客户端下载地址为 python-memcached

1   什么是memcached

memcached是一个高性能的、分布式内存对象缓存系统,尽管很通用,但是用来加速WEB应用、降低数据库负载时比较多。

Danga Interactive 开发了memcached用来提高 LiveJournal.com 的速度,这个站点每天处理2000万以上的动态页面请求,独立用户有100万左右。memcached把数据库的负载降到了几乎没什么事可干的地步,并为用户提供很快的页面响应速度,更好的资源利用率和更快的数据库存取操作。

2   它如何工作

首先启动一个memcached监护进程,监护进程不需要配置文件,只要在命令行里面加三四个参数就可以了:

# ./memcached -d -m 2048 -l 10.0.0.40 -p 11211

这里指定使用2GB内存,监听10.0.0.40的11211端口来启动memcached。因为32位处理器最多只能有4GB的地址空间。如果你确实需要32位的服务器处理4-64GB的内存(使用PAE),则每个使用2-3GB内存。

3   移植应用

Warning

pass

4   数据库不能做这些么

数据库为了在关系数据库管理系统上实现ACID,使用了锁,导致很多读写阻塞。而memcached从不会阻塞。

5   那共享内存呢

首先使用缓存的很多用户都是用于WEB。这意味着要分配时间出来做多请求处理给不同的系统,如mod_perl、PHP等等,这是对全局缓存的一种浪费。如果你使用多线程语言和共享内存API,如IPC::Shareable,你的每个线程都拥有独立的缓存。这个也是共享内存的局限性。

memcached服务器和客户端实现了全局缓存。实际上,很推荐你在同一台机器上同时运行WEB结点和memcached结点。这会节省一点网络开销。

6   MySQL 4.x的查询缓存如何

Warning

pass

7   数据库复制的对比

Warning

pass

8   memcached够快么

非常快,它使用 libevent 来处理任意数量的连接。在Linux上,尽可能使用 epoll 来实现。使用非阻塞的网络IO和计算,所以对象在不同的客户端上可能有不同的状态。还使用内置的内存块分配和哈希表算法,确保虚拟内存不会过来捣乱。

9   竞争情况

你可能感兴趣用户是否会获取一个过期的值。

服务器API只有一种获取数据的方法,并有3种提交数据的方法:

  • set 无条件的设置指定的键为给定的值。
  • add 添加到缓存,如果不存在。
  • replace 当存在已有值时,替换一下。

另外,这3个函数都可以设置过期时间。

10   memcached的Python客户端

10.1   基本使用

import memcache
mc=memcache.Client(['127.0.0.1:11211'],debug=0)
mc.set("some_key","Some value")
value=mc.get("some_key")
mc.set("another_key",3)
mc.delete("another_key)
mc.set("key","1") #用于自动增量/减量的必须是字符串
mc.incr("key")
mc.decr("key")

标准的使用memcache作为数据库缓存的方法如下:

key=derive_key(obj)
obj=mc.get(key)
if not obj:
    obj=backend_api.get(...)
    mc.set(obj)
#现在可以操作obj了

10.2   Client类

__init__(servers,debug=0,pickleProtocol=0,pickler=pickle.Pickler,unpickler=pickle.Unpickler)

构造函数

delete(key,time=0)

删除某个键。time的单位是秒,确保特定时间内的set/update操作会失败。返回1成功,0失败。

incr(key,delta=1)

给自增量变量加上delta,默认为1。

decr(key,delta=1)

给自减量变量减去delta,默认为1。

add(key,val,time=0,min_compress_len=0)

添加一个键值对,内部调用_set()方法。

replace(key,val,time=0,min_compress_len=0)

替换值,内部调用_set()方法。

set(key,val,time=0,min_compress_len=0)

无条件的设置键值对。time设置超时,单位是秒。min_compress_len用于设置zlib压缩。内部调用_set()方法。

set_multi(mapping,time=0,key_prefix=”,min_compress_len=0)

设置多个键值对。

get(key)

获取值。出错则返回None。

get_multi(keys,key_prefix=”)

获取多个键的值,返回字典。keys为健明列表。key_prefix是键名前缀,可以最终构成key_prefix+key的完整键名。与set_multi中一样。