可可熊的窝

Category Archives: 编程相关

用Python QQ写一个挂QQ工具

IN:Python   Tags: ,    Comments:10

Python QQ是好早以前就有的一个项目,不过因为很久没更新过,以前看到的时候不能登录,所以没怎么关注过,最近代码被开发者放在了google code上面,也做了些改动,目前可以登录,发送,接收消息了,不过不是很稳定。最近看了看这个项目的代码,对整个socket-qq分枝有了全面了解。在代码设计上也学到了不了东西:-)

Python QQ是在Windows上面开发的,所以我在Linux下测试的时候还有不少问题,最近改了改,然后做了个挂QQ的工具给草儿同学,很不完善的,也很不稳定,使用wxPython+threading完成,GUI+多线程确实是很折腾人的,在多线程更新GUI上使用了wx.CallAfter函数,可以查看limodou博客的介绍。

截个图上来:
oqq

先不发布了,继续完善Python QQ。

03-19
2009

发一个Python版的星际译王

IN:C, Python, 编程相关   Tags: ,    Comments:3

sdcv-0.4.2版本的代码有3480行,而图形界面的星际译王更是有N多的代码,俺也写了一个就十几行的Python代码,速度当然比不上sdcv,能差十倍,不过,请注意,sdcv查一个单词是0.01秒,我这个是0.1秒,我不觉得有人能感觉出来差别。

其实我的核心是C语言写的,之所以在速度上没有sdcv快是没有做那么些优化,俺只写了80多行,而且还有不少代码是用作Python封装的。我以前写文章说过sdcv代码写的很麻烦,用C语言可以很简洁的写出来,现在确实做到了,只是结合了Python。我觉得这种模式挺不错,影响速度的核心使用C语言去写,然后主逻辑框架使用Python写,不仅效率不会受影响,开发的速度也提高了不少。(我这个例子Python并没做什么)

static PyObject * lookup(PyObject *self, PyObject *args)
{
    int fd;
    char *file_prefix;
    long file_size;
    long wc;
    char *word;

    char *data;
    const char *p;
    long index_size;
    int offset;
    int size;
    int flag = 0;
    unsigned char *buf;

    if (!PyArg_ParseTuple(args, "slls:lookup",
                &file_prefix, &file_size, &wc, &word)) {
        return NULL;
    }
    char file_name[256];
    strcpy(file_name, file_prefix);
    strcat(file_name, ".idx");
    if ((fd = open(file_name, O_RDONLY)) < 0) {
        printf("open failedn");
        return NULL;
    }
    data = (char *)mmap( NULL, file_size, PROT_READ, MAP_SHARED, fd, 0);
    p = data;
    int i;
    for (i=0;i<wc;i++) {
        index_size = strlen(p) + 1 + 2*sizeof(int);
        if (strcmp(word, p) == 0) {
            flag = 1;
        }
        if (flag == 1) {
            offset = ntohl(*(int *)(p + strlen(p) + 1));
            size   = ntohl(*(int *)(p + strlen(p) + 1 + sizeof(int)));
            //printf("offset=%dnsize%dn",offset,size);
            /*gzFile zfile;
            zfile = gzopen("./dic/stardict-langdao-ec-gb-2.4.2/langdao-ec-gb.dict.dz", "rb");
            gzseek(zfile, offset, SEEK_SET);
            buf = (unsigned char *)malloc(*size+1);
            memset(buf, '', size+1);
            gzread(zfile, buf, size);
            printf("%sn", buf);
            */
            close(fd);

            if ((fd = open("./dic/stardict-langdao-ec-gb-2.4.2/langdao-ec-gb.dict", O_RDONLY)) < 0) {
                return NULL;
            }
            lseek(fd, offset, SEEK_SET);
            buf = (unsigned char *)malloc(size+1);
            memset(buf, '', size+1);
            read(fd, buf, size);
            //printf("%sn",buf);
            close(fd);
            return Py_BuildValue("s", buf);
        }
        p += index_size;
    }

    return Py_BuildValue("s","");
}

static struct PyMethodDef lookup_methods[] = {
    {"lookup", lookup, 1, "lookup(file_prefix, file_size, wc, word)"},
    {NULL, NULL}
};

void initlookup()
{
    (void) Py_InitModule("lookup", lookup_methods);
}

使用C语言对Python进行扩展挺方便的,http://gashero.yeax.com/?p=38#id7这里有个不错的文档。
完了俺整理整理也放在google code上去。

上面的代码中dict文件需要是未gzip压缩过的,如果在压缩过的我使用被注释掉的那段代码在seek的时候速度很慢,又没办法用mmap,所以暂时就先只使用未压缩过的。

02-26
2009

libevent学习-(I)

IN:C, 编程相关   Tags: ,    Comments:1

libevent是一个异步事件处理软件函式库,以BSD许可证释出。

libevent提供了一组应用程序编程接口(API),让程式设计师可以设定某些事件发生时所执行的函式,也就是说,libevent可以用来取代网络服务器所使用的循环检查架构。

摘自维基百科

http://blog.gslin.info/2005/11/network-programming-using-libevent-i.html
这里介绍了libevent相关的网络编程背景,需要带套访问哦。

以下分析针对libevent-1.4.3-stable。

来看libevent自带的例子:

/*
 * Compile with:
 * cc -I/usr/local/include -o event-test event-test.c -L/usr/local/lib -levent
 */

static void
fifo_read(int fd, short event, void *arg)
{
	char buf[255];
	int len;
	struct event *ev = arg;

	/* Reschedule this event */
	event_add(ev, NULL);

	fprintf(stderr, "fifo_read called with fd: %d, event: %d, arg: %pn",
		fd, event, arg);
	len = read(fd, buf, sizeof(buf) - 1);

	if (len == -1) {
		perror("read");
		return;
	} else if (len == 0) {
		fprintf(stderr, "Connection closedn");
		return;
	}

	buf[len] = '�';
	fprintf(stdout, "Read: %sn", buf);
}

int
main (int argc, char **argv)
{
	struct event evfifo;
	struct stat st;
	const char *fifo = "event.fifo";
	int socket;

	if (lstat (fifo, &st) == 0) {
		if ((st.st_mode & S_IFMT) == S_IFREG) {
			errno = EEXIST;
			perror("lstat");
			exit (1);
		}
	}

	unlink (fifo);
	if (mkfifo (fifo, 0600) == -1) {
		perror("mkfifo");<code></code>
		exit (1);
	}

	/* Linux pipes are broken, we need O_RDWR instead of O_RDONLY */
	socket = open (fifo, O_RDWR | O_NONBLOCK, 0);

	if (socket == -1) {
		perror("open");
		exit (1);
	}

	fprintf(stderr, "Write data to %sn", fifo);
	/* Initalize the event library */
	event_init();

	/* Initalize one event */
	event_set(&evfifo, socket, EV_READ, fifo_read, &evfifo);

	/* Add it to the active events, without a timeout */
	event_add(&evfifo, NULL);

	event_dispatch();
	return (0);
}

我把原来代码中WIN平台相关的去掉了,看起来方便一些,这个例子创建了一个pipe,并且使用libevent来监听是否可读,读有数据可读时调用函数fifo_read。
libevent调用比较简单,首先event_init()对event库进行初始化,然后使用event_set()来对某个fd的操作进行监听,接着使用event_add()把这个event激活,这里可以指定超时的时间,最后一步event_dispatch(),开始进行循环。

event_init()里只是对外的一个接口,这个函数调用了event_base_new(),分配了一个event_base类型的空间,设置了一些全局变量,使用detect_monotonic来检测是否支持CLOCK_MONOTONIC类型的时钟,这里不太理解为什么要使用clock_gettime(CLOCK_MONOTONIC, &ts)来获得当前时间,这个与gettimeofday得到的精度是一样的,只是一个是标准的时间(UNIX元年算起),一个是开机时间算起,有什么差别吗?

CLOCK_MONOTONICI测试代码:

结果:

[cocobear@cocobear libevent-1.4.3-stable]$ gcc ftime.c -lrt
[cocobear@cocobear libevent-1.4.3-stable]$ ./a.out
sec=1235372220
sec=4621

接下来就检测可使用的事件检测函数,这里与系统相关的调用被封装成了一个结构eventop:

struct eventop {
    const char *name;
    void *(*init)(struct event_base *);
    int (*add)(void *, struct event *);
    int (*del)(void *, struct event *);
    int (*dispatch)(struct event_base *, void *, struct timeval *);
    void (*dealloc)(struct event_base *, void *);
    /* set if we need to reinitialize the event base */
    int need_reinit;
};

编译时libevent会通过

#ifdef HAVE_SELECT
    &selectops,
#endif

来“动态”的确定eventops数组,在定义这个eventops数组时确定了使用这些事件驱动模型的顺序,如果你机子上有多种可用的模式,则可以通过修改改数组来自定义使用的模型。

在event_base_new()的最后调用了event_base_priority_init()初始化了消息的优先级队列。主要就是对activequeues变量进行空间分配。默认是分配了一个event_list给activequeues。

02-23
2009

PyFetion更新

IN:Python, 编程相关   Tags: ,    Comments:39

详细的更新请到google code 查看。

  1. get_info()函数参数处理who遗失的情况;
  2. 向服务器以HTTP方式提交密码时使用urllib.quote()编码;
  3. 修改send_msg()函数;
  4. 清理代码中直接退出的exit函数;
  5. 重写__tcp_recv()函数,以前这里有可能会丢失数据,比如好友列表过长;
  6. 增加隐身登录功能,login(True)表示隐身登录。

以前还有人提到增加隐身登录,我看了下08 PC版的飞信,只能是先登录,然后再设置隐身模式,这样的话增加设置隐身模式就没必要了。

至于登出飞信更是没必要了。

09.02.23 Update:

  1. 上次的代码get_uri被我改出错了,修正了一下;
  2. 修改了使用手机号直接发送的方式,因为目前可以使用tel: 13888888888的方式发送短信,不用从联系人中一个一个找了;不过以前似乎这种方式不行;
  3. 修正了获取联系人信息的XML数据,可以完整的获取联系人;
02-20
2009

libev编译篇

IN:C, 编程相关   Tags: ,    Comments:0

先给出libev的主页http://software.schmorp.de/pkg/libev.html,libev是一个高性能的事件驱动模型,与libevent类似,不过设计更为小巧,简洁。

libevent有成功的应用–memcached,libev是一个比较新的项目,代码比较少,所以这几天来研究下这个。

首先从CVS中下载最新的代码:

cvs -z3 -d :pserver:anonymous@cvs.schmorp.de/schmorpforge co libev

CVS代码中有autogen.sh文件,执行该文件会生成configure,我机子上出了点问题,需要首先运行

automake –add-missing

然后就是./configure && make && make install 了。
安装好后会有一个提示:

Libraries have been installed in:
/usr/local/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR’
flag during linking and do at least one of the following:
– add LIBDIR to the `LD_LIBRARY_PATH’ environment variable
during execution
– add LIBDIR to the `LD_RUN_PATH’ environment variable
during linking
– use the `-Wl,–rpath -Wl,LIBDIR’ linker flag
– have your system administrator add LIBDIR to `/etc/ld.so.conf’

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.

需要注意一下,因为默认这个库安装在了/usr/local/lib/里,所以运行程序时有可能会提示找不到libev.so这个动态库。我们需要在编译时加上-LLIBDIR参数,然后设置LD_RUN_PATH这个环境变量。

安装好为了测试libev,可以使用lighttz,其实我是从这里知道的libev,下载C文件,使用下面的命令来编译:

LD_RUN_PATH=/usr/local/lib/
export LD_RUN_PATH
gcc -LLIBDIR -o lighttz lighttz.c -lev

02-07
2009

导出抓虾收藏

IN:Python, 编程相关   Tags: ,    Comments:3

整理Python写的小工具,发现这个导出抓虾收藏的工具还比较有用,以前也是一同学让帮写的,也放在google code里面
代码

代码把抓虾收藏中的文章全部导出为html格式的书签,方便导入进delicious等书签。

02-04
2009
Page 4 of 22« First...234561020...Last »
loading...