人=吃饭+睡觉+上班+玩 , 猪=吃饭+睡觉 , 代入:人=猪+上班+玩 , 即:人-玩=猪+上班 . 结论:不懂玩的人=会上班的猪

Python字符串操作 不指定

zeus , 2010/07/01 21:55 , Python , Comments(0) , Reads(103) , Via Original
python如何判断一个字符串只包含数字字符
python 字符串比较

下面列出了常用的python实现的字符串操作
1.复制字符串

#strcpy(sStr1,sStr2)
sStr1 = 'strcpy'
sStr2 = sStr1
sStr1 = 'strcpy2'
print sStr2

2.连接字符串

#strcat(sStr1,sStr2)
sStr1 = 'strcat'
sStr2 = 'append'
sStr1 += sStr2
print sStr1

3.查找字符

#strchr(sStr1,sStr2)
sStr1 = 'strchr'
sStr2 = 'r'
nPos = sStr1.index(sStr2)
print nPos

4.比较字符串

#strcmp(sStr1,sStr2)
sStr1 = 'strchr'
sStr2 = 'strch'
print cmp(sStr1,sStr2)

5.扫描字符串是否包含指定的字符

#strspn(sStr1,sStr2)
sStr1 = '12345678'
sStr2 = '456'
#sStr1 and chars both in sStr1 and sStr2
print len(sStr1 and sStr2)

6.字符串长度

#strlen(sStr1)
sStr1 = 'strlen'
print len(sStr1)

7.将字符串中的小写字符转换为大写字符

#strlwr(sStr1)
sStr1 = 'JCstrlwr'
sStr1 = sStr1.upper()
print sStr1

8.追加指定长度的字符串

#strncat(sStr1,sStr2,n)
sStr1 = '12345'
sStr2 = 'abcdef'
n = 3
sStr1 += sStr2[0:n]
print sStr1

9.字符串指定长度比较

#strncmp(sStr1,sStr2,n)
sStr1 = '12345'
sStr2 = '123bc'
n = 3
print cmp(sStr1[0:n],sStr2[0:n])

10.复制指定长度的字符

#strncpy(sStr1,sStr2,n)
sStr1 = ''
sStr2 = '12345'
n = 3
sStr1 = sStr2[0:n]
print sStr1

11.字符串比较,不区分大小写

#stricmp(sStr1,sStr2)
sStr1 = 'abcefg'
sStr2 = 'ABCEFG'
print cmp(sStr1.upper(),sStr2.upper())

12.将字符串前n个字符替换为指定的字符

#strnset(sStr1,ch,n)
sStr1 = '12345'
ch = 'r'
n = 3
sStr1 = n * ch + sStr1[3:]
print sStr1

13.扫描字符串

#strpbrk(sStr1,sStr2)
sStr1 = 'cekjgdklab'
sStr2 = 'gka'
nPos = -1
for c in sStr1:
    if c in sStr2:
        nPos = sStr1.index(c)
        break
print nPos

14.翻转字符串

#strrev(sStr1)
sStr1 = 'abcdefg'
sStr1 = sStr1[::-1]
print sStr1

15.查找字符串

python strstr

#strstr(sStr1,sStr2)
sStr1 = 'abcdefg'
sStr2 = 'cde'
print sStr1.find(sStr2)

16.分割字符串

#strtok(sStr1,sStr2)
sStr1 = 'ab,cde,fgh,ijk'
sStr2 = ','
sStr1 = sStr1[sStr1.find(sStr2) + 1:]
print sStr1

Tags: , , ,
db.set_character_set('utf8')
dbc.execute('SET NAMES utf8;')
dbc.execute('SET CHARACTER SET utf8;')
dbc.execute('SET character_set_connection=utf8;')

"db" is the result of MySQLdb.connect
"dbc" is the result of db.cursor()
Tags: ,

关于tokyo cabinet的python库 不指定

zeus , 2010/03/19 16:07 , Python , Comments(0) , Reads(595) , Via Original
tokyo cabinet是一个很有名的缓存数据库,在网上大致的描述是这样的:tokyo cabinet 是日本人 平林幹雄 开发的一款 DBM 数据库,该数据库读写非常快,哈希模式写入100万条数据只需0.643秒,读取100万条数据只需0.773秒,是 Berkeley DB 等 DBM 的几倍。(其运行条件是:linux kernel 2.6.16, ext3的文件系统,Intel Xeon quad core 2.3GHz 8G RAM compile gcc4.2.3(-O3参数编译优化) glibc2.7),支持几乎所有的主流平台,除了windows,哈哈哈!比起windows来说可能linux,unix,mac os x会更好点。

我是今年年初的时候在杭州的时候接触这个好东东的,我们的系统也是要用它来做服务器缓存的,当时是用的c来做的,回到北京以后,参加了一次python的会课,那次会课恰恰清风提到了tokyo cabinet在python中的应用,不过他好像当时并没有现成的python封装库,自己完成的一些封装,tokyo cabinet已经有c,perl,ruby,java,lua的官方版本,可是就是唯有python没有,据说这个作者不会python有关系,由于现在我做的东西急需一个cache数据库,所有又打起了它的主意,昨天在晚上google了下,得来全不费功夫.

这是一个现成的tokyo cabinet的python封装库http://github.com/rsms/tc,不过先得编译安装tokyo cabinet的c库,安装过程如下:

wget http://1978th.net/tokyocabinet/tokyocabinet-1.4.43.tar.gz
tar zxvf tokyocabinet-1.4.43.tar.gz
cd tokyocabinet-1.4.43/
./configure
make
make install


然后再安装python的egg包,因为该项目是用git来管理的,所以先得安装git

git clone git://github.com/rsms/tc.git
cd tc
sudo python setup.py install

不过这里要注意有可能会出现有可能在安装的过程中会出现libtokyocabinet.so.8: cannot open shared object file: No such file or directory,请检查你的/etc/ld.so.conf文件,看它有没有包含你的tokyo cabinet的库路径,一般来讲tokyo cabinet会安装在/usr/local/lib下面,可以把这个路径写入/etc/ld.so.conf中,然后再ldconfig /etc/ld.so.conf就可以顺利安装了tc了

至于怎么去用,你可以参考下tc下的/lib/tc/test/的三个hdb.py,bdb.py,fdb.py的单元测试的例子,例子很详细
Tags: , ,

python模块之----os和os.path模块 不指定

zeus , 2010/03/14 01:02 , J2EE , Comments(0) , Reads(550) , Via Original
os和os.path模块
os.listdir(dirname):列出dirname下的目录和文件
os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。
os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
os.curdir:返回但前目录('.')
os.chdir(dirname):改变工作目录到dirname
os.sep 可以取代操作系统特定的路径分割符。
os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
os.remove()函数用来删除一个文件。
os.system()函数用来运行shell命令。
os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'

os.makedirs(dirname)创建多级目录,如:os.makedirs('/data/cc/ll/xx/zz')
os.mkdir(path) 创建多级目录
os.rmdir(path) # 删除目录 如:WIN: os.rmdir('E:\\book\\temp') LINUX: os.rmdir('/data/cc')
文件拷贝还可用shutil
import shutil
shutil.copyfile('listfile.py', 'd:/test.py') #复制文件
shutil.copystat(src,dst) #拷贝文件,连同文件的stat一起拷贝
shutil.copytree(src,dst) #拷贝目录,拷贝之前dst必须不存在

更多关于shutil的介绍请看python模块之----shutil模块
os.path.isdir(name):判断name是不是一个目录,name不是目录就返回false
os.path.isfile(name):判断name是不是一个文件,不存在name也返回false
os.path.exists(name):判断是否存在文件或目录name
os.path.abspath(name):获得绝对路径
os.path.normpath(path):规范path字符串形式
os.path.split(name):分割文件名与目录(事实上,如果你完全使用目录,它也会将最后一个目录作为文件名而分离,同时它不会判断文件或目录是否存在)
os.path.splitext():分离文件名与扩展名
os.path.join(path,name):连接目录与文件名或目录
os.path.basename(path):返回文件名
os.path.dirname(path):返回文件路径

os.path.getsize(name):获得文件大小(字节大小)如果name是目录返回0L
os.path.getctime(path) 返回浮点数的系统时间,在类Unix系统上是文件最近更改的时间, 在Windows上是文件或目录的创建时间
os.path.getmtime(path) 文件或目录最后更改的时间
os.path.getatime(path) 文件或目录最后存取的时间
os.path.samefile(path1,path2) 如果2个路径指向同样的文件或目录,返回True(Windows上不可用)

glob模块
glob.glob("*.py") #返回当前目录下所有以.py为后缀的目录或文件,glob("*.py") 里面可用正则去匹配,返回一个LIST列表.

python字符串方法 string模块 不指定

zeus , 2010/03/14 01:01 , Python , Comments(0) , Reads(530) , Via Original
字符串中字符大小写的变换:
* S.lower() #小写
* S.upper() #大写
* S.swapcase() #大小写互换
* S.capitalize() #首字母大写
* String.capwords(S) #这是模块中的方法。它把S用split()函数分开,然后用capitalize()把首字母变成大写,最后用join()合并到一起
* S.title() #只有首字母大写,其余为小写,模块中没有这个方法

字符串在输出时的对齐:
* S.ljust(width,[fillchar]) #输出width个字符,S左对齐,不足部分用fillchar填充,默认的为空格。
* S.rjust(width,[fillchar]) #右对齐
* S.center(width, [fillchar]) #中间对齐
* S.zfill(width) #把S变成width长,并在右对齐,不足部分用0补足

字符串中的搜索和替换:
* S.find(substr, [start, [end]])
#返回S中出现substr的第一个字母的标号,如果S中没有substr则返回-1。start和end作用就相当于在S[start:end]中搜索
* S.index(substr, [start, [end]])
#与find()相同,只是在S中没有substr时,会返回一个运行时错误
* S.rfind(substr, [start, [end]])
#返回S中最后出现的substr的第一个字母的标号,如果S中没有substr则返回-1,也就是说从右边算起的第一次出现的substr的首字母标号
* S.rindex(substr, [start, [end]])
* S.count(substr, [start, [end]]) #计算substr在S中出现的次数
* S.replace(oldstr, newstr, [count])
#把S中的oldstar替换为newstr,count为替换次数。这是替换的通用形式,还有一些函数进行特殊字符的替换
* S.strip([chars])
#把S中前后chars中有的字符全部去掉,可以理解为把S前后chars替换为None
* S.lstrip([chars])
* S.rstrip([chars]) 进行去除[chars]字符 如:s.rstrip('\n') 去掉换行符.
* S.expandtabs([tabsize])
#把S中的tab字符替换没空格,每个tab替换为tabsize个空格,默认是8个

字符串的分割和组合:
* S.split([sep, [maxsplit]])
#以sep为分隔符,把S分成一个list。maxsplit表示分割的次数。默认的分割符为空白字符
* S.rsplit([sep, [maxsplit]])
* S.splitlines([keepends])
#把S按照行分割符分为一个list,keepends是一个bool值,如果为真每行后而会保留行分割符。
* S.join(seq) #把seq代表的序列──字符串序列,用S连接起来

字符串的mapping,这一功能包含两个函数:
* String.maketrans(from, to)
#返回一个256个字符组成的翻译表,其中from中的字符被一一对应地转换成to,所以from和to必须是等长的。
* S.translate(table[,deletechars])
#使用上面的函数产后的翻译表,把S进行翻译,并把deletechars中有的字符删掉。需要注意的是,如果S为unicode字符串,那么就不支持 deletechars参数,可以使用把某个字符翻译为None的方式实现相同的功能。此外还可以使用codecs模块的功能来创建更加功能强大的翻译 表。

字符串还有一对编码和解码的函数:
* S.encode([encoding,[errors]])
#其中encoding可以有多种值,比如gb2312 gbk gb18030 bz2 zlib big5 bzse64等都支持。errors默认值为"strict",意思是UnicodeError。可能的值还有'ignore', 'replace', 'xmlcharrefreplace', 'backslashreplace' 和所有的通过codecs.register_error注册的值。这一部分内容涉及codecs模块,不是特明白
* S.decode([encoding,[errors]])

字符串的测试函数,这一类函数在string模块中没有,这些函数返回的都是bool值:
* S.startwith(prefix[,start[,end]]) #是否以prefix开头
* S.endwith(suffix[,start[,end]]) #以suffix结尾
* S.isalnum() #是否全是字母和数字,并至少有一个字符
* S.isalpha() #是否全是字母,并至少有一个字符
* S.isdigit() #是否全是数字,并至少有一个字符
* S.isspace() #是否全是空白字符,并至少有一个字符
* S.islower() #S中的字母是否全是小写
* S.isupper() #S中的字母是否便是大写
* S.istitle() #S是否是首字母大写的

字符串类型转换函数,这几个函数只在string模块中有:
* string.atoi(s[,base])
#base默认为10,如果为0,那么s就可以是012或0x23这种形式的字符串,如果是16那么s就只能是0x23或0X12这种形式的字符串
* string.atol(s[,base]) #转成long
* string.atof(s[,base]) #转成float

python list方法,运算详解 不指定

zeus , 2010/03/14 01:00 , Python , Comments(0) , Reads(774) , Via Original
List 的定义
li = ["a", "b", "mpilgrim", "z", "example"]

List元素定位使用
----------------------
>>> li[0]
'a'
>>> li[4]
'example'
>>> li[-1]
'example'
>>> li[-3]
'mpilgrim'
>>> li[1:3]
['b', 'mpilgrim']
>>> li[1:-1]
>>> li[:3]
['a', 'b', 'mpilgrim']
>>> li[3:]
['z', 'example']
>>> li[:]
['a', 'b', 'mpilgrim', 'z', 'example']

向 list 中增加元素
------------------------
>>> li.append("new")
>>> li
['a', 'b', 'mpilgrim', 'z', 'example', 'new']
>>> li.insert(2, "new")
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new']
>>> li.extend(["two", "elements"])
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
append 向 list 的末尾追加单个元素。
insert 将单个元素插入到 list 中。数值参数是插入点的索引。请注意,list 中的元素不必唯一,现在有两个独立的元素具有

'new' 这个值,li[2] 和 li[6]。
extend 用来连接 list。请注意不要使用多个参数来调用 extend,要使用一个 list 参数进行调用。在本例中,这个 list 有

两个元素。

extend (扩展) 与 append (追加) 的差别
---------------------------
>>> li = ['a', 'b', 'c']
>>> li.extend(['d', 'e', 'f'])
>>> li
['a', 'b', 'c', 'd', 'e', 'f']
>>> len(li)
6
>>> li[-1]
'f'
>>> li = ['a', 'b', 'c']
>>> li.append(['d', 'e', 'f'])
>>> li
['a', 'b', 'c', ['d', 'e', 'f']]
>>> len(li)
4

从 list 中删除元素
------------------------
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.remove("z")
>>> li
['a', 'b', 'new', 'mpilgrim', 'example', 'new', 'two', 'elements']
>>> li.remove("new")
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two', 'elements']

remove 从 list 中删除一个值的首次出现。

在 list 中搜索
--------------
>>> li
['a', 'b', 'new', 'mpilgrim', 'z', 'example', 'new', 'two', 'elements']
>>> li.index("example")
5
>>> li.index("new")
2

使用 list 的运算符
---------------------------
>>> li = ['a', 'b', 'mpilgrim']
>>> li = li + ['example', 'new']
>>> li
['a', 'b', 'mpilgrim', 'example', 'new']
>>> li += ['two']
>>> li
['a', 'b', 'mpilgrim', 'example', 'new', 'two']
>>> li = [1, 2] * 3
>>> li
[1, 2, 1, 2, 1, 2]

Lists 也可以用 + 运算符连接起来。list = list + otherlist 相当于 list.extend(otherlist)。但 + 运算符把一个新 (连
接后) 的 list 作为值返回,而 extend 只修改存在的 list。也就是说,对于大型 list 来说,extend 的执行速度要快一些。

Python 支持 += 运算符。li += ['two'] 等同于 li.extend(['two'])。+= 运算符可用于 list、字符串和整数,并且它也可以

被重载用于用户自定义的类中

* 运算符可以作为一个重复器作用于 list。li = [1, 2] * 3 等同于 li = [1, 2] + [1, 2] + [1, 2],即将三个 list 连接
成一个

Tags: , ,
1.打开文件代码如下:
>>> f = open(”d:test.txt”, “w”)

说明:第一个参数是文件名称,包括路径;第二个参数是打开的模式mode’r':只读(缺省。如果文件不存在,则抛出错误)’w':只写(如果文件 不存在,则自动创建文件)’a':附加到文件末尾’r+’:读写如果需要以二进制方式打开文件,需要在mode后面加上字符”b”,比如”rb”"wb” 等

2.读取内容f.read(size)参数size表示读取的数量,可以省略。如果省略size参数,则表示读取文件所有内容。 f.readline()读取文件一行的内容f.readlines()读取所有的行到数组里面[line1,line2,...lineN]。在避免将 所有文件内容加载到内存中,这种方法常常使用,便于提高效率。

3.写入文件f.write(string) 将一个字符串写入文件,如果写入结束,必须在字符串后面加上”n”,然后f.close()关闭文件

4.文件中的内容定位f.read()读取之后,文件指针到达文件的末尾,如果再来一次f.read()将会发现读取的是空内容,如果想再次读取全部内容,必须将定位指针移动到文件开始:
f.seek(0)这个函数的格式如下(单位是bytes):f.seek(offset, from_what)from_what表示开始读取的位置,offset表示从from_what再移动一定量的距离,比如f.seek(10, 3)表示定位到第三个字符并再后移10个字符。from_what值为0时表示文件的开始,它也可以省略,缺省是0即文件开头。下面给出一个完整的例 子:>>> f = open(’/tmp/workfile’, ‘r+’)
>>> f.write(’0123456789abcdef’)
>>> f.seek(5) # Go to the 6th byte in the file
>>> f.read(1)
‘5′
>>> f.seek (-3, 2) # Go to the 3rd byte before the end
>>> f.read(1)
‘d’

5.关闭文件释放资源文件操作完毕,一定要记得关闭文件f.close(),可以释放资源供其他程序使用

#打开文件和进行写操作
--------------------------------
f=open(’test.txt’,'w’)
f.write(’hello’)
f.writelines(['hi','haha'])#多行输入
f.close()
#append data
f=open(’test.txt’,'a’)
f.write(’hello’)
f.writelines(['hi','haha'])
f.close()
#连续写入后会自动关闭
open(’test.txt’,'a’).write(’11111rn’)
#把result里的元素依次填到open函数里去
result={’hello’,'u’}
exec open(’test.txt’) in result
#
selected = [] # temp list to hold matches
fp = open(’test.txt’)
for line in fp.readlines(): # Py2.2 -> “for line in fp:”
selected.append(line)
del line # Cleanup transient variable
#
open(’test.txt’).readlines()
file在python是一个特殊的类型,它用于在python程序中对外部的文件进行操作。在python中一切都是对象,file也不例外,file有file的方法和属性。下面先来看如何创建一个file对象:

* file(name[, mode[, buffering]])

file()函数用于创建一个file对象,它有一个别名叫open(),可能更形象一些,它们是内置函数。来看看它的参数。它参数都是以字符串的形式传递的。
name是文件的名字。
mode 是打开的模式,可选的值为r w a U,分别代表读(默认) 写 添加支持各种换行符的模式。用w或a模式打开文件的话,如果文件不存在,那么就自动创建。此外,用w模式打开一个已经存在的文件时,原有文件的内容会被清 空,因为一开始文件的操作的标记是在文件的开头的,这时候进行写操作,无疑会把原有的内容给抹掉。由于历史的原因,换行符在不同的系统中有不同模式,比如 在 unix中是一个n,而在windows中是’rn’,用U模式打开文件,就是支持所有的换行模式,也就说’r’ ‘n’ ‘rn’都可表示换行,会有一个tuple用来存贮这个文件中用到过的换行符。不过,虽说换行有多种模式,读到python中统一用n代替。在模式 字符的后面,还可以加上+ b t这两种标识,分别表示可以对文件同时进行读写操作和用二进制模式、文本模式(默认)打开文件。
buffering如果为0表示不进行缓冲;如果为1表示进行”行缓冲”;如果是一个大于1的数表示缓冲区的大小,应该是以字节为单位的。

file对象有自己的属性和方法。先来看看file的属性。
--------------------------------------
closed #标记文件是否已经关闭,由close()改写
encoding #文件编码
mode #打开模式
name #文件名
newlines #文件中用到的换行模式,是一个tuple
softspace #boolean型,一般为0,据说用于print

file的读写方法:
* F.read([size]) #size为读取的长度,以byte为单位
* F.readline([size])
#读一行,如果定义了size,有可能返回的只是一行的一部分
* F.readlines([size])
#把文件每一行作为一个list的一个成员,并返回这个list。其实它的内部是通过循环调用readline()来实现的。如果提供size参数,size是表示读取内容的总长,也就是说可能只读到文件的一部分。
* F.write(str)
#把str写到文件中,write()并不会在str后加上一个换行符
* F.writelines(seq)
#把seq的内容全部写到文件中。这个函数也只是忠实地写入,不会在每行后面加上任何东西。

file的其他方法:

* F.close()
#关闭文件。python会在一个文件不用后自动关闭文件,不过这一功能没有保证,最好还是养成自己关闭的习惯。如果一个文件在关闭后还对其进行操作会产生ValueError
* F.flush()
#把缓冲区的内容写入硬盘
* F.fileno()
#返回一个长整型的”文件标签”
* F.isatty()
#文件是否是一个终端设备文件(unix系统中的)
* F.tell()
#返回文件操作标记的当前位置,以文件的开头为原点
* F.next()
#返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。
* F.seek(offset[,whence])
# 将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了, whence可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进 行写操作时,文件操作标记会自动返回到文件末尾。
* F.truncate([size])
#把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。如果size比文件的大小还要大,依据系统的不同可能是不改变文件,也可能是用0把文件补到相应的大小,也可能是以一些随机的内容加上去。
简介:
urllib2是python的一个获取url(Uniform Resource Locators,统一资源定址器)的模块。它用urlopen函数的形式提供了一个非常简洁的接口。这使得用各种各样的协议获取url成为可能。它同时 也提供了一个稍微复杂的接口来处理常见的状况-如基本的认证,cookies,代理,等等。这些都是由叫做opener和handler的对象来处理的。

以下是获取url最简单的方式:

import urllib2
response = urllib2.urlopen('http://python.org/')
html = response.read()

许多urlib2的使用都是如此简单(注意我们本来也可以用一个以”ftp:”"file:”等开头的url取代”HTTP”开头的url).然而,这篇教程的目的是解释关于HTTP更复杂的情形。HTTP建基于请求和回应(requests &responses )-客户端制造请求服务器返回回应。urlib2用代 表了你正在请求的HTTP request的Request对象反映了这些。用它最简单的形式,你建立了一个Request对象来明确指明你想要获取的url。调用urlopen函 数对请求的url返回一个respons对象。这个respons是一个像file的对象,这意味着你能用.read()函数操作这个respon对象:

import urllib2

req = urllib2.Request('http://www.voidspace.org.uk')
response = urllib2.urlopen(req)
the_page = response.read()

注意urlib2利用了同样的Request接口来处理所有的url协议。例如,你可以像这样请求一个ftpRequest:

req = urllib2.Request('ftp://example.com/')

对于HTTP,Request对象允许你做两件额外的事:第一,你可以向服务器发送数据。第二,你可以向服务器发送额外的信息(metadata),这些信息可以是关于数据本身的,或者是关于这个请求本身的–这些信息被当作HTTP头发送。让我们依次看一下这些。

数据:
有时你想向一个URL发送数据(通常这些数据是代表一些CGI脚本或者其他的web应用)。对于HTTP,这通常叫做一个Post。当你发送一个你 在网上填的form(表单)时,这通常是你的浏览器所做的。并不是所有的Post请求都来自HTML表单,这些数据需要被以标准的方式encode,然后 作为一个数据参数传送给Request对象。Encoding是在urlib中完成的,而不是在urlib2中完成的。

import urllib
import urllib2

url = 'http://www.someserver.com/cgi-bin/register.cgi'
values = {'name' : 'Michael Foord',
'location' : 'Northampton',
'language' : 'Python' }

data = urllib.urlencode(values)
req = urllib2.Request(url, data)
response = urllib2.urlopen(req)
the_page = response.read()

如果你不传送数据参数,urlib2使用了一个GET请求。一个GET请求和POST请求的不同之处在于POST请求通常具有边界效应:它们以某种 方式改变系统的状态。(例如,通过网页设置一条指令运送一英担罐装牛肉到你家。)虽然HTTP标准清楚的说明Post经常产生边界效应,而get从不产生 边界效应,但没有什么能阻止一个get请求产生边界效应,或一个Post请求没有任何边界效应。数据也能被url自己加密(Encoding)然后通过一 个get请求发送出去。

这通过以下实现:
>>> import urllib2
>>> import urllib
>>> data = {}
>>> data['name'] = 'Somebody Here'
>>> data['location'] = 'Northampton'
>>> data['language'] = 'Python'
>>> url_values = urllib.urlencode(data)
>>> print url_values
name=Somebody+Here&language=Python&location=Northampton
>>> url = 'http://www.example.com/example.cgi'
>>> full_url = url + '?' + url_values
>>> data = urllib2.open(full_url)

头:
我们将会在这里讨论一个特殊的HTTP头,来阐释怎么向你的HTTP请求中加入头。
有一些网站不希望被某些程序浏览或者针对不同的浏览器返回不同的版本。默认情况下,urlib2把自己识别为Python-urllib/x.y(这里的xy是python发行版的主要或次要的版本号,如, Python-urllib/2.5),这些也许会混淆站点,或者完全不工作。浏览器区别自身的方式是通过User-Agent头。当你建立一个Request对象时,你可以加入一个头字典。接下来的这个例子和上面的请求一样,不过它把自己定义为IE的一个版本。

import urllib
import urllib2

url = 'http://www.someserver.com/cgi-bin/register.cgi'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
values = {'name' : 'Michael Foord',
'location' : 'Northampton',
'language' : 'Python' }
headers = { 'User-Agent' : user_agent }

data = urllib.urlencode(values)
req = urllib2.Request(url, data, headers)
response = urllib2.urlopen(req)
the_page = response.read()

Respons同样有两种有用的方法。当我们出差错之后,看一下关于info and geturl的部分。

异常处理:

不能处理一个respons时,urlopen抛出一个urlerror(虽然像平常一样对于python APIs,内建异常如,ValueError, TypeError 等也会被抛出。)
HTTPerror是HTTP URL在特别的情况下被抛出的URLError的一个子类。
urlerror:
通常,urlerror被抛出是因为没有网络连接(没有至特定服务器的连接)或者特定的服务器不存在。在这种情况下,含有reason属性的异常将被抛出,以一种包含错误代码和文本错误信息的tuple形式。

e.g.
>>> req = urllib2.Request('http://www.pretend_server.org')
>>> try: urllib2.urlopen(req)
>>> except URLError, e:
>>> print e.reason
>>>
(4, 'getaddrinfo failed')

当一个错误被抛出的时候,服务器返回一个HTTP错误代码和一个错误页。你可以使用返回的HTTP错误示例。这意味着它不但具有code属性,而且同时具有read,geturl,和info,methods属性。>>> req = urllib2.Request('http://www.python.org/fish.html')>>> try:>>> urllib2.urlopen(req)>>> except URLError, e:>>> print e.code>>> print e.read()>>>404...... etc

容错:
如果你准备处理HTTP错误和URL错误这里有两种基本的方法,我更倾向于后一种:

1.
from urllib2 import Request, urlopen, URLError, HTTPError
req = Request(someurl)
try:
response = urlopen(req)
except HTTPError, e:
print 'The server couldn\'t fulfill the request.'
print 'Error code: ', e.code
except URLError, e:
print 'We failed to reach a server.'
print 'Reason: ', e.reason
else:
# everything is fine

注意:HTTP错误异常必须在前面,否则URL错误也会捕获一个HTTP错误。
2
from urllib2 import Request, urlopen, URLError
req = Request(someurl)
try:
response = urlopen(req)
except URLError, e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server couldn\'t fulfill the request.'
print 'Error code: ', e.code
else:
# everything is fine

注意:URL错误是IO错误异常的一个子类。这意味着你能避免引入(import)URL错误而使用:

from urllib2 import Request, urlopen
req = Request(someurl)
try:
response = urlopen(req)
except IOError, e:
if hasattr(e, 'reason'):
print 'We failed to reach a server.'
print 'Reason: ', e.reason
elif hasattr(e, 'code'):
print 'The server couldn\'t fulfill the request.'
print 'Error code: ', e.code
else:
# everything is fine

极少数环境下,urllib2能够抛出socket.error.

INFO and GETURL
urlopen返回的response(或者HTTP错误实例)有两个有用的方法:info和geturl。

geturl–它返回被获取网页的真正的url。这是很有用的,因为urlopen(或使用的opener对象)也许会伴随一个重定向。
获取的网页url也许和要求的网页url不一样。

info–它返回一个像字典的对象来描述获取的网页,尤其是服务器发送的头。它现在一般是httplib.HTTPMessage的一个实例。
典型的头包含'Content-length', 'Content-type', 等等。看一下Quick Reference to HTTP Headers中,HTTP头列表,还有
关于他们简单的解释和使用方法。
Openers 和Handlers
当你获取一个URL时,你使用一个opener(一个可能以一个比较迷糊名字命名的实例–urllib2.OpenerDirector)。正常情况下
我们一直使用默认的opener,通过urlopen,但你也可以创建自定义的openers。opener使用操作器(handlers)。所有的重活都交给这些handlers来做。每一个handler知道
怎么打开url以一种独特的url协议(http,ftp等等),或者怎么处理打开url的某些方面,如,HTTP重定向,或者HTTP cookie。

你将会创建openers如果你想要用安装特别的handlers获取url,例如,获取一个处理cookie的opener,或者一个不处理重定向的opener。

枚举一个OpenerDirector,然后多次调用.add_handler(some_handler_instance)来创建一个opener。
或者,你可以用build_opener,这是一个很方便的创建opener对象的函数,它只有一个函数调用。build_opener默认会加入许多
handlers,但是提供了一个快速的方法添加更多东西和/或使默认的handler失效。
其他你想要的handlers能够处理代理,authentication和其他平常但是又有些特殊的情况。
install_opener能被用于创建一个opener对象,(全局)默认的opener。这意味着调用urlopen将会用到你刚安装的opener。
opener对象有一个open方法,它可以被直接调用来获取url以一种和urlopen函数同样的方式:没有必要调用install_opener,除非是为了方便。

Basic Authentication:(基本验证)

为了解释创建和安装一个handler,我们将会使用 HTTPBasicAuthHandler。更多关于这个东西的内容和详细讨论—包括一个 Basic Authentication如何工作的解说–参见 Basic Authentication Tutorial.

当需要Authentication的时候,服务器发送一个头(同时还有401代码)请求Authentication。它详细指明了一个Authentication和一个域。这个头看起来像:

Www-authenticate: SCHEME realm=”REALM”.
e.g.
Www-authenticate: Basic realm=”cPanel Users”

客户端然后就会用包含在头中的正确的帐户和密码重新请求这个域。这是”基本验证”。为了简化这个过程,我们可以创建一个
HTTPBasicAuthHandler和opener的实例来使用这个handler。
HTTPBasicAuthHandler用一个叫做密码管理的对象来处理url和用户名和密码的域的映射。如果你知道域是什么(从服务器发送的authentication
头中),那你就可以使用一个HTTPPasswordMgr。多数情况下人们不在乎域是什么。那样使用HTTPPasswordMgrWithDefaultRealm就很方便。它
允许你为一个url具体指定用户名和密码。这将会在你没有为一个特殊的域提供一个可供选择的密码锁时提供给你。我们通过提供None作为add_password方法域的参数指出
这一点。
最高级别的url是需要authentication的第一个url。比你传递给.add_password()的url更深的url同样也会匹配。

# create a password manager
password_mgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
# Add the username and password.
# If we knew the realm, we could use it instead of “None“.
top_level_url = “http://example.com/foo/”
password_mgr.add_password(None, top_level_url, username, password)

handler = urllib2.HTTPBasicAuthHandler(password_mgr)
# create “opener” (OpenerDirector instance)
opener = urllib2.build_opener(handler)
# use the opener to fetch a URL
opener.open(a_url)
# Install the opener.
# Now all calls to urllib2.urlopen use our opener.
urllib2.install_opener(opener)

注意:在以上的示例中我们只给build_opener提供了HTTPBasicAuthHandler。默认opener有对普通情况的操作器 (handlers)- ProxyHandler, UnknownHandler, HTTPHandler, HTTPDefaultErrorHandler, HTTPRedirectHandler, FTPHandler, FileHandler, HTTPErrorProcessor.
高级别url实际上是一个完整的url(包括http:协议组件和主机名可选的端口号),如”http://example.com”或者是一个授权(同样,主机名,可选的端口号)
如”"example.com” 或 “example.com:8080″(后一个示例包含了一个端口号)。授权,如果被呈现,一定不能包含用户信息-如”oe@password:example.com”
是不正确的、
代理:
urllib2将会自动检测你的代理设置并使用它们。这是通过 ProxyHandler实现的,它是操作器链的一部分。正常情况下,这是个好东西,但是也有它不那么有用的偶然情况。
一个做这些的方法是安装我们自己的ProxyHandler,不用任何定义任何代理。使用一个和建立Basic Authentication操作器相似的步骤可以实现:

>>> proxy_support = urllib2.ProxyHandler({})
>>> opener = urllib2.build_opener(proxy_support)
>>> urllib2.install_opener(opener)
注意:
目前urllib2不支持通过代理获取HTTPs位置。这是一个问题。
sockets和layers
python支持获取层叠的网页的源码。urllib2使用httplib library,而httplib library反过来使用socket library。
对于python2.3你可以指明一个socket应该在超时之前等待response多久。这在这些不得不获取网页的应用中很有用。默认socket模块没有超时而且能够挂起。
目前,socket超时在urllib2或者httplib水平中不可见。然而,你可以全局地为所有socket设置默认的超时。

import socket
import urllib2
# timeout in seconds
timeout = 10
socket.setdefaulttimeout(timeout)
# this call to urllib2.urlopen now uses the default timeout
# we have set in the socket module
req = urllib2.Request('http://www.voidspace.org.uk')
response = urllib2.urlopen(req)

所谓工欲善其事,必先利其器。Python开发有很多工具,其中Eclipse+Pydev就是其中比较常见的一种。

    下面将开发环境的安装配置过程写下来,供后来者参考。

一、安装Eclipse SDK。

到 http://download.eclipse.org/eclipse/downloads/ 找SDK最新的Release版本,最新的版本是 3.5.1

下载。一开始我选择的是台湾的[Taiwan] National Center for High-Performance Computing (http) ,速度只有5kB/s,还是小日本的快,118kB/S,, Japan Advanced Institute of Science and Technology (http) ,做事情应该也这样,一个明显很缓慢,就要当即力断换其他的。

下载完毕之后,将eclipse SDK解压到某个目录下,我的放在e:\eclipse就可以了。

如果要使用中文的,最好是使用跟SDK配套的语言包,否则也不能完全汉化(最后我选择了纯英文的,没汉化)。根据网上的资料,汉化前不要启动Eclipse,否则不能完全汉化。将语言包也解压到同一目录下即可。

二、安装Pydev

到 http://sourceforge.net/projects/pydev/ 这里找最新版本下载,最新版本是: 1.5.4

下载后解压,将plugins目录下所有文件挪到Eclipse的相应目录下,将feature目录下所有文件挪到Eclipse的相应目录下,最后启动 Eclipse,在Help-》Software Upates-》Manage Configuration,然后弹出的界面即可看到pydev的插件。

另一种安装插件的方法是:Help-》Software Upates-》Find and Install-》Search for new features to install-》New remote site-》随便起个name如pydev,url填 http://pydev.org/updates -》然后照着提示下载安装即可。
这里要注意,官方文档写了一个sf镜像可以用 实际上是不可以用的。

推荐我选择的是后一种方法。

三 、Pydev的配置
在Eclipse IDE 下, 打开 Window->Preferences... 对话框,从右侧的树形列表中选择“ PyDev”->“Interpreter Python”, 点击New按钮,从Python的安装路径下选择Python.exe,然后会弹出一个对话框让你勾选System PYTHONPATH,我是都选了,应该无所谓。最后点Ok,退出。


四、进行Django项目开发

1、建立PyDev Project

Eclipse IDE-》File-》New-》Other-》Pydev-》选择Pydev Project-》起一个项目的名称(例如demo)-》选择路径,如E:\work-》选择适合你的Python版本(我的是2.5)-》将下面的勾去掉,不要建立src文件-》Finish

2、建立Django Project

(1)django-admin.py startproject demo。

(2)把生成的Django项目目录拷贝到Eclipse刚刚建立的项目下的目录里。回到刚才的Elicpse IDE-》在PyDev Package视图中右键单击新建的项目,从弹出的菜单中选择“Refresh”,即可看到Django的项目工程。添加、删除文件和目录的操作都可以通过右键菜单来完成。

(3)右键单击PyDev项目-》属性-》选择PyDev-》PYTHONPATH-》然后将src目录 (项目文件路径) 添加到项目代码中去-》确定


(4)对Pydev项目进行配置:选择Pydev的项目名称-》Run菜单-》Open Run Dialog-》Python Run-》右键New-》在Main面板中写入项目名称,通过Browse载入项目名称和Main Module,Main Module选择manage.py-》在Augement面板中,argument必须是 runserver --noreload,下面的working directory加入你的base directory。

打完收工,接下来开始写Django应用吧。

最后补一个用SourceInsight看Python工程的方法:
1、到http://www.sourceinsight.com/public/languages/下载Python.CLF文件,这是python的语言支持包。
2、打开SourceInsight->Options > Preferences -> Languages -> Import -> Select (.CLF)
3、再做的:-> Document Types - > Add Type (Give it a name : 填Python->.给出类型名:我填的是*.py ) 在下面的下拉框里面选择之前导入的文件,然后确定。Source Insight 就可以识别该类型的文件了。
Tags: , ,

Python sqlite3和单元测试 不指定

zeus , 2010/02/26 10:12 , Python , Comments(0) , Reads(563) , Via Original
import os
import unittest            # 包含单元测试模块
import sqlite3 as sqlite   # 包含sqlite3模块

def get_db_path():
   return "sqlite_testdb"

class TransactionTests(unittest.TestCase):  # 单元测试第一步: 由TestCase派生类
   def setUp(self): # 单元测试环境配置
       try:
           os.remove(get_db_path())
       except:
           pass

       self.con1 = sqlite.connect(get_db_path(), timeout=0.1) # 连接数据库
       self.cur1 = self.con1.cursor() # 获取游标

       self.con2 = sqlite.connect(get_db_path(), timeout=0.1)
       self.cur2 = self.con2.cursor()

   def tearDown(self): # 单元测试环境清除
       self.cur1.close() # 关闭游标
       self.con1.close() # 关闭连接

       self.cur2.close()
       self.con2.close()

       os.unlink(get_db_path())

   def CheckDMLdoesAutoCommitBefore(self):
       self.cur1.execute("create table test(i)") # 执行SQL查询
       self.cur1.execute("insert into test(i) values (5)")
       self.cur1.execute("create table test2(j)")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 1) # 测试

   def CheckInsertStartsTransaction(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 0)

   def CheckUpdateStartsTransaction(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       self.con1.commit()
       self.cur1.execute("update test set i=6")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchone()[0]
       self.failUnlessEqual(res, 5)

   def CheckDeleteStartsTransaction(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       self.con1.commit()
       self.cur1.execute("delete from test")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 1)

   def CheckReplaceStartsTransaction(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       self.con1.commit()
       self.cur1.execute("replace into test(i) values (6)")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 1)
       self.failUnlessEqual(res[0][0], 5)

   def CheckToggleAutoCommit(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       self.con1.isolation_level = None
       self.failUnlessEqual(self.con1.isolation_level, None)
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 1)

       self.con1.isolation_level = "DEFERRED"
       self.failUnlessEqual(self.con1.isolation_level , "DEFERRED")
       self.cur1.execute("insert into test(i) values (5)")
       self.cur2.execute("select i from test")
       res = self.cur2.fetchall()
       self.failUnlessEqual(len(res), 1)

   def CheckRaiseTimeout(self):
       self.cur1.execute("create table test(i)")
       self.cur1.execute("insert into test(i) values (5)")
       try:
           self.cur2.execute("insert into test(i) values (5)")
           self.fail("should have raised an OperationalError")
       except sqlite.OperationalError:
           pass
       except:
           self.fail("should have raised an OperationalError")

class SpecialCommandTests(unittest.TestCase):
   def setUp(self):
       self.con = sqlite.connect(":memory:")
       self.cur = self.con.cursor()

   def CheckVacuum(self):
       self.cur.execute("create table test(i)")
       self.cur.execute("insert into test(i) values (5)")
       self.cur.execute("vacuum")

   def CheckDropTable(self):
       self.cur.execute("create table test(i)")
       self.cur.execute("insert into test(i) values (5)")
       self.cur.execute("drop table test")

   def CheckPragma(self):
       self.cur.execute("create table test(i)")
       self.cur.execute("insert into test(i) values (5)")
       self.cur.execute("pragma count_changes=1")

   def tearDown(self):
       self.cur.close()
       self.con.close()

def suite(): # 单元测试第二步
   default_suite = unittest.makeSuite(TransactionTests, "Check")
   special_command_suite = unittest.makeSuite(SpecialCommandTests, "Check")
   return unittest.TestSuite((default_suite, special_command_suite)) # 用例

def test(): # 单元测试第三步
   runner = unittest.TextTestRunner()
   runner.run(suite()) # 运行单元测试

if __name__ == "__main__":
   test()
Pages: 1/2 First page 1 2 Next page Final page [ View by Articles | List ]