python中的module

很惭愧,虽然之前用python打过几次酱油,也号称自己看了那个简明教程,但事实上,我还是不熟呐。

恰巧最近又被python的timezone处理搞的极其郁闷,那么记一点自己看到的关于package和module的资料吧,日后好查。

说白了,package是一个文件夹,文件夹下面有__init__.py,而module对应的是文件,文件名为module.py。

import 和 from import 有以下几种格式:

import module #导入module,module在python可以搜索到的path中

from package import module # 导入package中的module,package在python可以搜索到的path中

from module import function # 导入module中的function

from package import * # 导入package中所有的module,哪些module需要导入?由__init__.py 中的__all__决定

from module import * # 导入module中所有的变量

可以看到from import的用法还是很复杂的。

另外一个简单的规则,import后面的变量名可以直接用了。

 

参考资料:

http://docs.python.org/tutorial/modules.html

http://docs.python.org/reference/simple_stmts.html#the-import-statement

http://www.effbot.org/zone/import-confusion.htm

http://woodpecker.org.cn/diveintopython/object_oriented_framework/importing_modules.html

Share "python中的module"

Share on: FacebookTwitter

从nginx的cookie中获得用户访问的时间

由于需要跟踪用户行为,在nginx服务端使用user模块开启了nginx的cookie,使用服务器来设置cookie而不是通过程序来设置的好处在于:

1 比较简单,不需要自己写程序维护

2 图片等静态文件也可以设置cookie

本想通过分析log获得用户第一次入站的时间,但通过观察nginx的log,发现它设置的cookie有以下规律:

1 32位的sid,第一个8位和第三个8位的值相同,最后一个8位的值是等差数列

2 第二个8位的后4位相同,前面4位不同

nginx sid样例:

9000A8C0 6E15 AD4D 734A84B1 02180303
9000A8C0 4616 AD4D 734A84B1 02190303
9000A8C0 D616 AD4D 734A84B1 021A0303

鉴于有这么明显的规律,我认定其中必有私货。上IRC问了一下,暂时没人回答,于是决定自己看看源代码。

按图索骥,根据nginx wiki 上列的模块关系,一下可以找到user对应的代码为:

svn cat svn://svn.nginx.org/nginx/trunk/src/http/modules/ngx_http_userid_filter_module.c

nginx的代码非常清楚,代码看起来也比较易读,在534行左右可以看到uid的各个元素的值

ctx->uid_set[0] = htonl(conf->service); // 与服务有关,为定值

ctx->uid_set[1] = htonl((uint32_t) ngx_time()); // 嗯,服务端的时间

ctx->uid_set[2] = htonl(start_value); // 不太清楚,从变量名来看应该为服务启动时间,启动后不会变化

ctx->uid_set[3] = htonl(sequencer_v2); // 一个sequence,每一次都会加,到了一定的阈值再重置

既然这样,那么上面说的第二个8位就是时间戳了。

由于该时间戳通过htonl进行了转换,按network byte order(也就是big endian)编码,我们使用时就需要调用ntohl转换成本地的字节顺序。

简单的c++程序如下:

#include <arpa/inet.h>
#include <iostream>
using namespace std;
int main(int argv, char ** argc){
cout << "ntohl" << endl;
cout << ntohl(0xD616AD4D) << endl;
return 0;
}

输出的结果为 1303189206,嗯,后面的事情,大家都知道了。

如果用php,简单的代码如下:

<?php
$str = "D616AD4D";
$splited = str_split($str, 2);
$splited = array_reverse($splited);
$str = implode('', $splited);
print hexdec($str);
?>

其实就是自己手动实现了一把big endian 到 little endian的转换:将byte的次序换了一下。

以上纯属个人看法,如有不对,希望拍砖,谢谢~

 

 

Share "从nginx的cookie中获得用户访问的时间"

Share on: FacebookTwitter

更新recovery的一个巧妙方法

这是我当时刷新我手机recovery所使用的一种方法,在此备份一下,如果你的recovery无法刷新,可以试试用这个方法。

看了几篇更新recovery1.5.2的帖子,总体感觉是非常简单的,核心就是一条命令。
但tim版(32A SPL 1.33.0008 S-ON,目前装rom为安卓3.04)却更新失败,这些问题经过搜索也没有满意的结果。
经过自己的实验,发现一种可行的办法,和大家分享一下,希望能够有用,如有不对,还请诸位拍砖。

常用的刷recovery1.5.2 方法可能会有以下问题:

out of memory 错误
使用的命令:
flash_image recovery recovery.img
问题的具体情况可以参考这个链接: http://www.hiapk.com/bbs/thread-63257-1-1.html

FAILED (remote: signature verify fail) 错误
使用的命令:
fastboot flash recovery img/recovery.img
既然flash_img不行,那就使用fastboot,结果发现报签名错误,应该是s-on的缘故吧。
(xda上推荐的方法就是刷spl了,可是现在我的recovery都进不去了,而且我还不想刷spl)

header is the same, not flashing recovery 错误
该方法已经有点麻烦了,原理是先使用recovery.img 启动,然后再刷recovery。

引用帖子(http://www.android.net/bbs/viewthread.php?tid=9926&;extra=pageD1&page=1):

1. 进入fastboot模式
2. 跟电脑连上,装驱动什么的当然要
3. fastboot boot recovery.1.4.img
boot后面跟要刷的recovery的镜像
adb shell mount -a
挂载一切设备(指手机内的ROM和SD卡),忽略其他错误
adb push recovery.1.5.img /system/recovery.img
adb push recovery.1.5.img /sdcard/recovery.1.5.img
adb shell flash_image recovery /sdcard/recovery.1.5.img
4. 重启

结果还是不行,报上面的错。

header is the same, not flashing recovery

大概意思是文件的内容一样,既然这样,本人就想了一个投机的方法:
将启动所使用的recovery改成一个低版本的,然后刷1.5.2的recovery
具体方法如下:

下载一个老一点的recovery版,我下的是1.3.2,地址:http://forum.xda-developers.com/showthread.php?t=530492
1. 进入fastboot模式(手机开机时按返回键和电源键)
2. 跟电脑连上,装好驱动,开启usb调试模式
3. 在sdk目录的命令行下输入 fastboot boot recovery.1.3.2.img
(此处的 recovery.1.3.2.img 即为刚下的老版本recovery,无需拷贝至手机)
手机再次重启,进入1.3.2的recovery模式
然后在pc cmd端上输入以下命令:
adb shell mount -a
(挂载一切设备(指手机内的ROM和SD卡),忽略其他错误)
adb push recovery.1.5.2.img /system/recovery.img
adb push recovery.1.5.2.img /sdcard/recovery.1.5.2.img
adb shell flash_image recovery /sdcard/recovery.1.5.2.img
4. 重启

最后提醒大家,刷机有风险,刷前需谨慎。

Share "更新recovery的一个巧妙方法"

Share on: FacebookTwitter

几个工具使用小结

1 mac os 上使用vmware server console

  • 打开X11程序(应用程序 》 实用程序)
  • 在出现的bash中输入 ssh -Y username@servername
  • 进入server端后,输入vmware,即可启动vmware server console,但奇怪的是su后,反而提示没有权限

 

2 列模式

vi 列模式:

  • ctrl+v 进入 visual block模式
  • 上下选择要编辑的列或者通过{n}j 或者 G 来选择
  • I(大写的i)回到第一行,并进入插入模式
  • 输入完成后按esc进行列修改,其他如删除则按d

textwrangler列模式:

  • 先按住option,然后再做选择
  • 对选择的区域进行移动(暂时不能更多操作)

 

3 excel几个常用的功能

  • 只复制筛选后的结果(alt+;)
  • 去掉重复数据(增加一辅助列,列内容为公式=countif($A$1:A2, A2)),然后过滤掉大于1的数据

 

 

 

 

Share "几个工具使用小结"

Share on: FacebookTwitter

sql常见错误和优化

下面的讨论仅仅针对mysql,版本为5.0。

一、错误的sql

下面说的错误的sql都是语法没有错,但是实际的功能和原来的有很大的差异,在此一记以警戒自己。

1 select 字段时忘记写逗号

正确sql: select a,b from table

错误sql:select  a b from table

要命的是这个sql并不报语法错误,本想取两个字段,结果是取了一个字段a,别名为b,有时候你查了半天为什么数据不对,结果是漏掉一个分号所致。

2 delete只写了字段,没有写完整条件

正确sql: delete from table where a = 1

错误sql:delete from table where a

上面的错误sql也不报语法错误,但是后果很严重,直接把所有的数据删掉。所以delete的时候一定要小心,同时建议delete时加上limit和更多确定的条件,这样增加一点点保险。

3 update时条件不完整

正确sql:update table table1, table2 set table1.a = '...' where table2.join = table1.join and table2.b = '**'

错误sql:  update table table1, table2 set table1.a = '...' where table2.b = '**'

上面的错误sql杀伤力也是很大的,直接将table1的数据都修改一遍,我们同事就犯过这个错误,最后大家修数据修的快挂了。

4 select join时,字段写错

正确sql : select table1.a, table2.b from table1 inner join table2 on table1.join = table2.join

错误sql:select table1.a, table2.b from table1 inner join table2 on table1.join = table1.join

注意后面的条件是同一个表的字段相等,这在任何情况下都是true,这样的话,内连接直接变成笛卡尔乘积,如果两个大表,系统直接挂掉,我犯过此错误,在测试环境上数据少,没仔细看结果,没有发现问题,上到正式环境上,mysql直接挂掉。

5 时间没有加单引号

正确sql:select a from table1 where d > '2011-03-11'

错误sql: select a from table1 where d > 2011-03-11

你会发现错误的sql后面的结果过滤没有达到你期望的结果。


二、mysql 优化部分

优化前建议先开启slowlog,分析mysql的slowlog,分析slowlog也有很多工具,自带的mysqldumpslow就还不错。

下面是自己总结的一些tips

1 合理的表结构

核心表中避免存大数据,允许合理的冗余数据存在。

2 加索引

这是最简单的办法,大部分情况下,是没有加索引,或者索引做的不对。是否该加索引,explain一下就知道了。

3 避免join的字段类型不对

同样的属性,在不同表里面保存的类型不一样,join完全无法使用索引,这时候如果无法对目前的表结构修改,可以使用cast作为暂时的解决方案。另外,join时,确保两个字段的确是同一个属性也非常重要,我们之前就犯过userId = user_id这样的低级错误,不但速度慢,而且结果也不对。

4 根据目前的条件,推导出更加有效的条件

如,根据实际需求有以下sql: select a.field1, b.field2 from a inner join b on a.join = b.join where {conditona}

如果你能够通过a表上的一条限制条件 {conditiona} 推导出一个b表上的限制条件{conditionb},而 {conditionb} 又能够明显减少查询的记录或者能够有效的使用索引,那么加上{conditionb}后的效果是非常显著的。

5 要多看看explain的结果

即使同一个条件,条件里面的取值不一样,explain出来的结果也是不一样的。

当然,在数据量非常大时,explain的结果即使看起来很美好,但也可能很慢。

6 业务上的,去掉返回大数据量的需求

当一条sql要返回几十万或者更多的数据给用户看,这sql可能就不应该存在,和业务部门谈谈,也许他们根本不需要这样的结果。

Share "sql常见错误和优化"

Share on: FacebookTwitter

lucene 相关小结

前不久工作中重新使用了一下lucene,比以前更加清晰点了,记点小结,以备后用。

1 Document 类:

此类是索引文档的最小单元,它可以理解成一个Hashmap,可以有各种各样的属性(Field),任何你要索引的内容都需要转成这个Document才能加入到索引中。

2 Analyzer 类:

分词器,建索引时,将文章中的text分成一个一个的term,然后term做反向索引。搜索时,将搜索的词分成一个一个的term,然后到索引中查找,目前lucene中自带的smartcn分词器用来中文分词也还不错。

3 几个疑问:

Q: lucene的IndexWriter 和 IndexReader是线程安全的吗?

A:答案是线程安全,IndexReader和IndexWriter的关系大概就是读写锁的关系。

Q:可以对一个目录同时进行索引和搜索的过程吗?

A:当然是了,这里我之前的疑问是:如果我建索引的过程中,删了某些Document,搜索是不是马上就搜不出结果了?答案是这种情况不会出现,搜索还是可以搜出来的,需要IndexWriter.close()且对IndexReader进行reopen才能起效。reopen的使用可以参考apache的文档

Q:是否可以按某个条件搜索索引,然后删除这部分Document?

A:可以,参考官方文档,而且还有updateDocument可用。

Share "lucene 相关小结"

Share on: FacebookTwitter

wordpress很方便呢

不得不说,wordpress实在很方便。手机上能够发blog,处理comment什么的。

而且各个平台的手机基本上都能支持,做一个blog能做到如此境界,不禁佩服一下。

Share "wordpress很方便呢"

Share on: FacebookTwitter

重新开始blog

任何时候开始做一件事情都不晚,只要你愿意。

对于我来说,blog就是这样。

虽然之前因为种种原因,blog中断,但不管过去如何,现在重新开始吧。

Share "重新开始blog"

Share on: FacebookTwitter

blog built using the cayman-theme by Jason Long. LICENSE