PHP and Python学习

来源:互联网 发布:淘宝买大麻种植暗语 编辑:程序博客网 时间:2024/06/13 05:40

1PHP语言

1.1使用范围

web服务器控制脚本桌面程序

1.2特点

解释型语言:解释器php适用环境:unix.linux,widows支持mysql,db2,dbase,odbc,oracle等数据库支持soap,snmp,pop3,smtp,com,corba等协议关联站点:http://www.runoob.com/python/python-tutorial.htmlhttp://www.w3school.com.cn/index.html

1.3基本语法

大小写不敏感
语法与c类似

"#! /usr/bin/php<?phpprint “hello world”;?>"

1.3.1变量

$x,变量名前面加$动态语言,无需预先设置变量类型;

1.3.2数组

定义

数组的关键字是”array”用()将内容包括,元素之间用,分隔Php中数组包括两个部分:关键字和数值关键字是整数或者字符串$array=array(5=>”one”,6=>”second”)如果没有映射关系,默认关键字是下标,下标从0开始:$array=(1,3,4)数组可以嵌套

引用:

$b=array[关键字]

使用:

新增:$b[新关键字]=值修改:$b[原关键字]=值清除:uset($b[关键字])或uset($b)清除所有打印数组print_r($b)

1.3.3运算符

1.3.4控制

条件

if,elseif(expr) {statement}else{statement}替换写法:if expr:elseif:endifswitchswitch expr{case condition1:statemen1 ;break;}

循环

for;foreach,whilefor(start;condition;expr){Statement;}foreach(组合 as 元素){Statement}

包括

require,include;require_onceinclude_once

1.4类

class,public,private

1.4.1属性

属性定义赋值时必须是常数,不能是运算得到的

class test {Public a=3;Private b=3;Public foo()}

访问:

$test=new test;$test->a;$test->foo();对于静态成员要用self::成员名来访问

扩展:

Class a extends B{this->成员}

1.5函数

定义

函数名($a,$b...){statement}可以用func_nums_args,func_get_args,func_get_arg来获得可变参数

2 Python

2.1 使用范围

web后台脚本日常维护

2.2 特点

解释型语言:解释器python,动态数据类型,面向对象适用环境:unix.linux,widows支持mysql,db2,dbase,odbc,oracle等数据库支持soap,snmp,pop3,smtp,com,corba等协议

2.3 基本语法

大小写敏感

"#! /usr/bin/pythonprint “hello world”

语法与c类似,但是不用括号表示结构的边界,而是通过缩进来表示

2.3.1 注释:

用’#’注释单条语句用’’’来注释多条语句

2.3.2 变量

动态数据类型,无需预先设置变量类型;

编码问题:

ascii编码是7位bit,只能表示127种字符,unicode编码是2个byte,将世界的语言编码都统一了,比如u"[\u4e00-\u9fa5]"#中文u'[\u3040-\u409f]#日文 片假名u'[\uac00-\ud7ff]#韩文在python中用u’xxx’表示unicode,xxx可以是直接输入的字符或者象上面用\u数字来表示.utf8是可变长编码,用1-6个字节来表示字符.通常中文用3个字节来表示.在内存中一般用unicode来表示字符,在存储和数据传输时通常采用utf8编码以节省空间和传输时间.对于字符串类型变量都有encode和decode函数,encode函数是将unicode转换成想要的字符比如str.encode('utf8'),decode是将其他类型字符转换成unicode字符,比如将文件存储的utf8数据转换成unicode数据,str.decode('utf8').此外,还有codecs模块,可以用来做转换工作.import codecswith codecs.open(xxxfilename,’rb’,’utf8’) as f  str=f.read()就可以避免在str中再做转换了.

codecs支持的编码如下:

编码 别名 支持语言 ascii 646, us-ascii English big5 big5-tw, csbig5 Traditional Chinese big5hkscs big5-hkscs, hkscs Traditional Chinese cp037 IBM037, IBM039 English cp424 EBCDIC-CP-HE, IBM424 Hebrew cp437 437, IBM437 English cp500 EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500 Western Europe cp720 Arabic cp737 Greek cp775 IBM775 Baltic languages cp850 850, IBM850 Western Europe cp852 852, IBM852 Central and Eastern Europe cp855 855, IBM855 Bulgarian, Byelorussian, Macedonian, Russian, Serbian cp856 Hebrew cp857 857, IBM857 Turkish cp858 858, IBM858 Western Europe cp860 860, IBM860 Portuguese cp861 861, CP-IS, IBM861 Icelandic cp862 862, IBM862 Hebrew cp863 863, IBM863 Canadian cp864 IBM864 Arabic cp865 865, IBM865 Danish, Norwegian cp866 866, IBM866 Russian cp869 869, CP-GR, IBM869 Greek cp874 Thai cp875 Greek cp932 932, ms932, mskanji, ms-kanji Japanese cp949 949, ms949, uhc Korean cp950 950, ms950 Traditional Chinese cp1006 cp1026 ibm1026 Turkish cp1140 ibm1140 Western Europe cp1250 windows-1250 Central and Eastern Europe cp1251 windows-1251 Bulgarian, Byelorussian, Macedonian, Russian, Serbian cp1252 windows-1252 Western Europe cp1253 windows-1253 Greek cp1254 windows-1254 Turkish cp1255 windows-1255 Hebrew cp1256 windows-1256 Arabic cp1257 windows-1257 Baltic languages cp1258 windows-1258 Vietnamese euc_jp eucjp, ujis, u-jis Japanese euc_jis_2004 jisx0213, eucjis2004 Japanese euc_jisx0213 eucjisx0213 Japanese euc_kr euckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001 Korean gb2312 chinese, csiso58gb231280, euc- cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso- ir-58 Simplified Chinese gbk 936, cp936, ms936 Unified Chinese gb18030 gb18030-2000 Unified Chinese hz hzgb, hz-gb, hz-gb-2312 Simplified Chinese iso2022_jp csiso2022jp, iso2022jp, iso-2022-jp Japanese iso2022_jp_1 iso2022jp-1, iso-2022-jp-1 Japanese iso2022_jp_2 iso2022jp-2, iso-2022-jp-2 Japanese, Korean, Simplified Chinese, Western Europe, Greek iso2022_jp_2004 iso2022jp-2004, iso-2022-jp-2004 Japanese iso2022_jp_3 iso2022jp-3, iso-2022-jp-3 Japanese iso2022_jp_ext iso2022jp-ext, iso-2022-jp-ext Japanese iso2022_kr csiso2022kr, iso2022kr, iso-2022-kr Korean latin_1 iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1 West Europe iso8859_2 iso-8859-2, latin2, L2 Central and Eastern Europe iso8859_3 iso-8859-3, latin3, L3 Esperanto, Maltese iso8859_4 iso-8859-4, latin4, L4 Baltic languages iso8859_5 iso-8859-5, cyrillic Bulgarian, Byelorussian, Macedonian, Russian, Serbian iso8859_6 iso-8859-6, arabic Arabic iso8859_7 iso-8859-7, greek, greek8 Greek iso8859_8 iso-8859-8, hebrew Hebrew iso8859_9 iso-8859-9, latin5, L5 Turkish iso8859_10 iso-8859-10, latin6, L6 Nordic languages iso8859_11 iso-8859-11, thai Thai languages iso8859_13 iso-8859-13, latin7, L7 Baltic languages iso8859_14 iso-8859-14, latin8, L8 Celtic languages iso8859_15 iso-8859-15, latin9, L9 Western Europe iso8859_16 iso-8859-16, latin10, L10 South-Eastern Europe johab cp1361, ms1361 Korean koi8_r Russian koi8_u Ukrainian mac_cyrillic maccyrillic Bulgarian, Byelorussian, Macedonian, Russian, Serbian mac_greek macgreek Greek mac_iceland maciceland Icelandic mac_latin2 maclatin2, maccentraleurope Central and Eastern Europe mac_roman macroman Western Europe mac_turkish macturkish Turkish ptcp154 csptcp154, pt154, cp154, cyrillic-asian Kazakh shift_jis csshiftjis, shiftjis, sjis, s_jis Japanese shift_jis_2004 shiftjis2004, sjis_2004, sjis2004 Japanese shift_jisx0213 shiftjisx0213, sjisx0213, s_jisx0213 Japanese utf_32 U32, utf32 all languages utf_32_be UTF-32BE all languages utf_32_le UTF-32LE all languages utf_16 U16,utf16 all languages utf_16_be UTF-16BE all languages (BMP only) utf_16_le UTF-16LE all languages (BMP only) utf_7 U7, unicode-1-1-utf-7 all languages utf_8 U8, UTF, utf8 all languages utf_8_sig all languages

base64编码

为了使用可见字符传输二进制数据,将二进制数据每3个字节分成一组,将这3个字节再分成4组,每组有6个bit,而2^6=64,这样就可以用可见字符来表示二进制数据了.如果二进制数据最后有1个或2个多余的字节,则用\x0来补足,同时,在编码末尾补充一个或二个=,表示补充的字节数.

模块有base64

import base64base64.b64encode(‘’)和base64.b64decode(‘’)

base64常用于url,cookie,少量的二进制文件传输(电子邮件)

数据转换

为了将字符串和二进制数值相互转换

import structstruct.pack(‘转换格式’,数据字符串)   #将数据字符串转换成二进制数据struct.unpack(‘转换格式’,二进制字符串)    #将二进制字符串转换成数据例如:struct.pack(‘h’,1024)    #将1024按照2字节的小头序转换(低字节在前)输出:/x00/x04struct(‘>h’,1024)   #将1024按照2字节的大头序(网络次序)转换(高字节在前)输出:/x04/0x00struct.unpack(‘h’,’/x00/x04’)输出:1024转换字符:i表示按照4字节转换整数,h表示按照2字节转换整数,>表示按照大头序,不带>表示按照小头序转换.
Format C Type Python type Standard size Notes c char char 1 1 b signed char integer 1 (3) B unsigned char integer 1 (3) ? Bool bool 1 (1) h short integer 2 (3) H unsigned short integer 2 (3) i int integer 4 (3) I unsigned int integer 4 (3) l long integer 4 (3) L unsigned long integer 4 (3) q long long integer 8 (2), (3) Q unsigned long long integer 8 (2), (3) f float float 4 (4) d double float 8 (4) s char[] string p char[] string P void * integer (5), (3)

2.3.3 数组

Python中的数组有两种:一种是可变的叫list用[]来表示;
一种是不可变的叫tuple,用()来表示,不像php需要有关键字来标识.

可变的数组:

Array=[1,3];Array.append(3);在最后一个位置添加Array.insert(1,4);在第二个位置插入Array.pop();删除最后一个Array.pop(1);删除第二个位置的数数组的数从位置0开始,-1表示最后一个.-2表示倒数第二个;

不可变数组:

不可变指的是该索引所指向的数不变,如果数组中包括可变数组,则可变数组的内容是可以变的,但是在不可变数组中指向该可变数组的指向并没有变;Array=(1,3,[4,5]);需要注意的是在不可变数组中如果只有一个数也要加上逗号以免歧义

字典

dict实际上是一种映射:dict={key:value,key2:value2}dict=['a':1,'b':2];可以使用dict[key]来访问,用pop来删除;可以使用get方法来判断是否存在元素;需要注意的是:key是唯一区分数组元素的标识,所以重复的key以后面的为准.Set表示关键字组合:与dict不同的是里面不存value创建set需要提供一个list例如set=set([1,2]).可以使用add(key),remove(key)来操作;但是如果添加重复的key不会有效果;可以从数组中切一块下来[起始位置:终点位置]注意:实际操作中如果将数组赋值给另一个数组,则这两个数组指向同一个地址,而不是数值相等.

列表生成式:

a=[x*x for x in range(10) if x%2==0]

生成器:

如果一个函数中有yield关键字,则这个函数就成为一个生成器,不是直接打印而是返回一个list;#! /usr/bin/pythondef yang():        u=[1]        while True:                yield u                u.append(0)                u=[u[i]+u[i-1] for i in range(len(u))]j=0for i in yang():        print i        j=j+1        if j==10:                break杨辉三角形

数组进阶collections

命名tuple
tuple是用下标来获取元素值,不太直观,可以用命名tuple来获取元素.如此比定义一个类方便.
from collections import namedtuple
namedtuple(tuple名,[元素名])
例如:point=namedtuple(“point”,[‘x’,’y’]
point(1,2)
point.x
point.y

deque

为了方便插入删除list中的元素.from collections import deque d=deque([‘a’,’b’])d.appendleft(‘x’)#在list头加入元素,不像list一样需要用下标d.popleft()#在头部删除元素d.append()#在尾部加入元素d.pop()#在尾部删除元素

defaultdict

defaultdict用来当引用dict中不存在的元素时,返回一个默认值import defaultdict from collectionsdd=defaultdict(lambda:’N/A’)dd[‘a’]=1dd[‘a’]dd[‘b’]#返回N/A

OrderedDict

dict插入时key是无序的,采用OrderedDict使得key按照插入顺序来排列from collections import OrderedDict od=OrderedDict([‘a’:1,’b’:2,’c’:3])

Counter

counter用来根据key来计算key出现的次数from collections import Counterch=Counter()for i in str:  ch[i]=ch[i]+1counter返回的是一个dict{‘xx’:xx,’xx’:xx...}#注意,访问dict对象是通过key来访问的xxdict.[关键字]Counter构造函数输入的是一个list,Counter.most_common(排名前几位)返回的是排名前几位的list对象.例子:搜索文章中排名前10位的单词from collections import Counterimport rewords=re.findall(r’\w+’,open(‘test.py’,’r’).read())ch=Counter(words).most_common(10)for i in range(len(ch)):  print ch[i]

2.3.4 运算符

注意下面表达式的区别:

a,b=b,a+b#假如a,b开始为1,2则执行后,a,b为2,3;在赋值之前a,b变量值是原来的值.a=bb=a+b

执行前a,b为1,2.执行后a,b为2,4.区别就在于后者执行第一条语句后a的值就发生的变化,而上面的表达式执行给b赋值的语句时,a的值没有发生变化.

2.3.5 控制

与c类似,但是没有括号来表示边界而是通过缩进:
条件

if expr :    statementelse    statement

循环

for 元素 in 组合    statement组合是一个list.或者用range来生成一个范围;range([start],stop,[step])while expr:    statement

2.4 类

class,public,private    class 类名(继承类名)      __init__(self,其他参数):             self.xx=xx

构造函数,self是必须的,指向类本身

获取类信息:

Type:type(实例名)dir:dir(实例名)isinstance(实例名,类名)

实例属性优先于类属性,如果实例属性与类属性相同,将覆盖类属性.实例属性可以动态增减.del 实例.属性

2.4.1 动态类

类在实例化后可以用实例.成员的方法来改变属性和方法,但是如果仅仅是对实例做上面的操作,仅仅是改变实例的成员.如果需要改变该类的成员,就要把实例改成类.
同时,如果在类的定义中加入slot限制,可以限制动态添加成员,只能动态添加在slot中的成员.

from types import MethodTypeclass student(object):       __slots__=('name','age','add_fun')s=student();s.name='han's.age=32print s.name,s.agedef add_fun(self,xxx):    print 'hello,add fun's.add_fun=MethodType(add_fun,s)s.add_fun('a')s2=student()student.add_fun=add_funs2.add_fun('a')getattrgetattr可以在类中没有需要的成员时,返回一个默认的成员值       class attr(object):           def __init__(self,path=''):               self._path=path           def __str__(self):               return self._path           def __getattr__(self,x):               return attr("%s/%s"%(self._path,x))       print attr().a.b.c       Run:       a/b/c

2.4.2 元类:

元类是为了创建类结构,是类结构的模板.一般我们是静态的创建类结构,然后根据类结构创建类实例.但是,为了能够动态的创建类结构,引进了元类的概念.

class listmetaclass(type):    def __new__(cls,name,bases,attr):        attr['add']=lambda self,value:self.append(value)        return type.__new__(cls,name,bases,attr)class MyList(list):    __metaclass__=listmetaclass#指出该类为元类l=MyList()l.add(1)print l

在这个例子中,为list类增加了一个属性add.

2.4.3 使用property

使用property的目的是简化类函数的定义,不要对类成员使用get,set方法

class screen:    @property    def width(self):#相当于调用get方法        return self._width    @width.setter#相当于调用set方法    def width(self,value):         self._width=values=screen()s.width=19print s.width

2.4.4 自定义类:

为了实现类似int的用法,比如可以循环,数组,需要自定义类

class screen(object):    def __init__(self,a=0):        self.a=a        self.b=0    def __str__(self):        return 'screen class attrib a is %s'%self.a    def __iter(self):        return self    def __next(self):        self.a=self.a+1        if self.a>100:            raise StopIteration        return self.a    def __getitem__(self,n):        self.a=n+self.a        if self.a>100:            raise StopIteration                return self.a s=screen()for i in screen():    print i

从实例来看,为了使screen类能够构成list,必须定义iter,getitem函数,next可以不定义.而且,函数的下划线必须是程序中的形式.

2.5 调试

2.5.1 异常捕获:

Try…except…finally

try:    l=MyList()    l.add(1)    print (l)except ValueError :    print ('SrandardError')finally:    print ('finally')

2.5.2 Log

import logging#引入loggnglogging.basicConfig(level=logging.INFO)#设置logging级别debug,info,warning,errorclass listmetaclass(type):    def __new__(cls,name,bases,attr):        logging.info('new:')        attr['add']=lambda self,value:self.append(value)        return type.__new__(cls,name,bases,attr)

2.5.3 单元调试

编写单元模块测试函数

import unittestfrom test import MyListclass TestMyList(unittest.TestCase):    def setUp(self):#表示在测试方法前调用的函数        print('\nstart')    def tearDown(self):#表示在测试方法后调用的函数        print ('\nteardown')    def test_init(self):#表示用于测试类成员的函数,名字前面是test        d=MyList()        self.assertEquals(d[0],1)if __name__=='__main__':    unittest.main()执行python mytest.pyRun:startEteardown======================================================================ERROR: test_init (__main__.TestMyList)----------------------------------------------------------------------Traceback (most recent call last):  File "mytest.py", line 10, in test_init    self.assertEquals(d[0],1)IndexError: list index out of range----------------------------------------------------------------------Ran 1 test in 0.000sFAILED (errors=1)

2.6 函数

2.6.1 函数定义

def 函数名(参数):    statement参数可以是单个变量,默认参数,list或tuple,或者是dict如果是list或tuple,参数前加*如果是dict,参数前加**Dict参数是类似a=xx,b=xx形式的

2.6.2 引入其他模块:

import xxfrom 库名 import 模块名安装python模块可以用:pip install 库名,或者easy_install 库名函数指针:f=abs()f(-10)   10,相当于将函数指针赋给了一个变量;

2.6.3 map和reduce函数

map和reduce函数用来将一个函数作用在一组变量上,参数都是一个函数和一个组合。

map函数的函数参数只需要一个变量:

def fun(x):    return x*xlist1=map(fun,[1,2,3])print list1run:[1,4,9]

reduce函数的函数参数需要两个变量,用来将2个变量合成一个变量以便于与下一个变量继续计算

def fun(x,y):       return x+ya=reduce(fun,[1,2,4])run:7

2.6.4 filter 函数

filter函数从一个组合中筛选出符合条件的组合,需要两个参数,一个是组合,一个是筛选函数:

def f(x):    return x%2==0l=filter(f,range(10))print lRun:[0, 2, 4, 6, 8]

2.6.5 sorted函数:

sorted函数用来对组合排序,是一个抽象函数,需要两个参数数,一个是组合一个是排序函数

def f(x):    return x[1]str=[('a',5),('b',2),('c',3),('d',4)]str2=sorted(str,key=f)print str2Run: [('b', 2), ('c', 3), ('d', 4), ('a', 5)]

2.6.6 返回函数

返回函数是指在一个函数中再定义一个函数,然后将这个函数赋值给一个变量,如果直接调用这个函数,将不会产生结果,直到用这个变量被调用.内部的函数接受输入的参数.

def f(*args):def inter_fun():     ax=0     for i in args          ax=ax+i          return ax   return inter_funs=f(1,2,3)  #此时不会返回结果s()  #此时才会返回结果相当于是函数指针.Run:6

2.6.7 匿名函數:

有时为了不显式定义函数,可以采用匿名函数形式

Y=lambda x:x*xY(2)

2.6.8 装饰函数:

装饰函数的作用是给一个函数添加新方法

def f(func):def wrapper_fun(*args,**kw):     print “decorator %s”%func.__name__     func(*args,**kw)return wrapper_fun   @f   def f():       print ‘this is f’   f()   run   decorator f   this is f关键字:@修饰符,wrapper如果需要传入参数给f,需要再包一层def f(para):   def decorator_fun(f):def wrapper_fun(*args,**kw):        print “%s decorator %s”%para,func.__name__        f(*args,**kw)          rerurn wrapper_fun    return decorator_fun   @f(‘sss’)   def f():       print ‘this is f’   f()   run   aaa decorator f   this is f

2.6.9 文件函数

f=open(路径,打开方式)打开方式可以是’r’,’w’,’rb’,’wb’f.read([size])[.decode(编码方式)],比如f.read().decode(‘gbk’)read默认是读入所有内容,如果文件太大,则可以给size参数readlines 返回以每行为元素的list;可以for i in f.readlines();如果要编码还可以使用module:codecs,则要import codecscodecs.open()f.close()#关闭文件如果不想每次都关闭文件可以用:with open as f     f.xxx

2.6.10 os模块:

os模块中封装了系统命令

import osos.name#操作系统名字os.uname()#操作系统详细信息os.environ#环境参数os.getenv(环境变量参数)#例如os.getenv(‘path’)os.path.abspath(目录)#获得目录的绝对路径os.path.join(目录1,目录2)#将目录合并,注意不要用字符串合并,而要用join,否则可能由于操作系统不同而变化.os.mkdir(xxx)os.rmdir(xxx)os.path.split(xxx)#将路径分解成目录和文件名os.path.splitext(xxx)#分解扩展文件名os.rename(xxx,xxx)#改名os.remove(xxx)#删除文件os.listdir(xxx)#列出文件os.path.isdir(xxx)#是否是文件夹shutil模块中有copyfile()函数

序列化:

就是将dict变成字符流,serialization

python中的序列化方法是cpickle或pickle,还有就是json(java script object)pickle方法只能用在python中,而json方法可以跨平台dict_str=dict(name=’a’,age=20)try :       import cpickle:expect importerror:       import picklep=pickle.dumps(dict_str)#将dict序列化pickle.loads(p)#反序列化,将序列化流反成dict对象with open(‘dump.txt’,’wb’) as f:       pickle.dump(dict_str,f)with open(‘dump.txt’,’rb’) as f       pickle.load(f)#从文件中反序列化Import jsonj=json.dumps(dict_str)json.loads(j)with open(‘dump.txt’,’wb’) as f:#将dict序列化后输出到文件中       json.dump(dict_str,f)with open(‘dump.txt’,’rb’) as f       json.load(f)#从文件中反序列化Json对象的{}对应python的dictJson对象的[]对应python的list上面讲的的是对dict对象进行序列化,如果需要对类进行序列化,需要对类进行加工.class strudent:       def __init__(self,name,age,scope):           self._name=name           self._age=age           self.scope=scopedef student2dict(std):#需要将类转换成json的dict       return{‘name’:std.name,’age’:std.age,’scope’:std.scope}s=student(‘bog’,28,1)import jsonjson.dumps(s,default=student2dict)也可以不写上面的函数,由于类中默认有一个dict所以可以写成json.dumps(s,default=lambda obj:obj.__dict__)为了反序列化,同样的需要将dict对象变成class对象def dict2student(dict):       return student(d[‘name’],d[‘age’],d[‘scope’])josn_str={‘name’:’bog’,’age’:20,’scope’:18}json.loads(json_str,object_hook=dict2student)

2.6.11 多进程,多线程,分布式进程

Python中的多进程可以用fork,Process来实现,fork方法是unix下的方法,Porcess是跨平台的方法

import ospid=os.fork()if pid==0:       print (‘i\’m a child process’)else:       print (‘i\’m a parent process’)或者:from multiprocessing import Processimport osdef run_proc(name):#指定进程函数       print (‘run a child process%s’%name)if __name__=’__main__’:       print (‘parent process %d is run’%os.getpid())       p=Process(target=run_proc,args=(‘test’,))#注册进程       print (‘process will start’)       p.start()#启动进程       p.join()#终止进程       print (‘end process’)

线程:

与process类似

import time,threadingdef loop():    for i in range(20):        time.sleep()        print (‘in thread’)t=threading.thread(target=loop)t.start()t.join()

分布式进程

分布式进程就是将进程分配到多个计算机中(工作者),由一个管理者通过网络管理任务分配.
相关类有:Queue,BaseManager
实现思想:管理者创建队列,分别是发送队列和结果队列.管理者创建队列管理者注册这两个队列并建立网络服务,向发送队列中输出任务.
工作者负责执行任务,主要步骤是工作者也创建一个队列管理者,注册队列,队列名与管理者注册的队列名一致,然后与管理者建立连接,接收队列,执行队列中的任务.

Taskmanager.py

#test muliti processing#first:type 'python taskmanager.py',then this prog will run #second:type in other terminal 'python taskworker.py'import random,time,Queuefrom multiprocessing.managers import BaseManagertask_queue=Queue.Queue()result_queue=Queue.Queue()class QueueManager(BaseManager):    passQueueManager.register('get_task_queue',callable=lambda :task_queue)QueueManager.register('get_result_queue',callable=lambda:result_queue)manager=QueueManager(address=('',5000),authkey='abc')manager.start()task=manager.get_task_queue()result=manager.get_result_queue()for i in range(10):    n=random.randint(0,1000)    print('put task %s'%n)    task.put(n)print ('Try get result...')for i in range(10):    r=result.get(timeout=10)    print ('Result:%s'%r)manager.shutdown()

Taskworker.py

import time,sys ,Queuefrom multiprocessing.managers import BaseManagerclass QueueManager(BaseManager):    passQueueManager.register('get_task_queue')QueueManager.register('get_result_queue')server_add='127.0.0.1'print ('connect to server:%s'%server_add)m=QueueManager(address=(server_add,5000),authkey='abc')m.connect()task=m.get_task_queue()result=m.get_result_queue()while True:    if task.empty():break    try:        n=task.get(timeout=1)        print ('run task %d*%d...'%(n,n))        r='%d*%d=%d'%(n,n,n*n)        time.sleep(1)        result.put(r)    except Queue.Empty:        print('task queue is empty')print ('worker is end')Run:管理者:    python taskmanager.py     put task 778    put task 405    put task 561    put task 760    put task 911    put task 583    put task 370    put task 309    put task 383    put task 699    Try get result...    Result:778*778=605284    Result:405*405=164025    Result:561*561=314721    Result:760*760=577600    Result:911*911=829921    Result:583*583=339889    Result:370*370=136900    Result:309*309=95481    Result:383*383=146689    Result:699*699=488601工作者:    python taskworker.py     connect to server:127.0.0.1    run task 778*778...    run task 405*405...    run task 561*561...    run task 760*760...    run task 911*911...    run task 583*583...    run task 370*370...    run task 309*309...    run task 383*383...    run task 699*699...    worker is end

2.6.12 正则表达式:

正则表达式用来匹配字符,最简单的是用’*’来匹配任意字符,用’?’来匹配一个字符.其余的有以下规则:不加转义符,如‘a’,表示要匹配a字符加转义符:’\d’:匹配数字‘\w’:匹配字符字符和数字‘\s’:匹配一个空格,’\s+’:至少一个空格范围匹配:[]:用来匹配一个范围,如[a-z],如果后面加+,则表示至少匹配一个这样的字符^表示行开始,比如^\d表示必须以数字开始$表示行结束,比如\d$表示必须以数字结束{}:表示需要匹配的个数,比如\d{3}表示匹配3个数字,\d{3,8}表示匹配3到8个数字.a|b:表示条件或,比如[p|p]ython,表示匹配python或python注意有些特殊字符需要转义:如\-,\_等python中的正则表达式使用:在python中\也是转义符,所以要是定义成字符串时,对于用于转义的\也要转义,就要定义成\\,为了方便在转义符之前加上r’xxx’,就不需要写成\\形式了python中使用转义符需要import re,调用函数是matchimport rere.match(r’^\d{3}\-\d{3,8}$’,’010-12345’)用来匹配电话号码match如果成功则返回一个match对象,否则返回none分组:通过在正则表达式中使用()可以将结果分组,用group(x)来提取,0表示原字符比如上面例子中需要提取区位号码和电话号码m=re.match(r’^(\d{3})\-(\d{3,8}$)’,’010-12345’)m.group(1)是010m.group(2)是12345切分字符串:为了从字符串中提取需要的内容,常常需要切分字符串,这时使用正则表达式可以起到很大作用.比如re.split(r’\s’+,’a b    c’)输出为[‘a’,’b’,’c’]>>> re.split(r'[\s,;]+','a b ;  , c')['a', 'b', 'c']将空格,逗号,分号都除掉了匹配中文:re_words=re.compile(u"[\u4e00-\u9fa5]")#中文m=re_words.search(s,0)print mprint m.group()word=re.findall(re_words,s)上面的程序曾经出现没有找到匹配中文的情况,是由于字符串编码没有采用unicode.

2.6.13 hashlib

用来计算散列值

import hashlibmd5=hashlib.md5()md5.update(‘str’)md5.hexdigest()#返回128位的数据sha1=hashlib.sha1()#计算160位的sha1数据

2.6.14 itertools

itertools可以构造一个可用于循环的数据集合,在构造时并不存在,只有在循环的时候才存在.

import itertoolsn=itertools.count(x)#构造一个以x为起点的无限增长的数for i in n:       print i输出:无限长的数repeat(x)#重复cycle(‘xxx’)#循环groupby(‘xxx’[,分组函数])#将内容按照关键字分组,相同内容分一组返回key和group例如:m=itertools.groupby(‘aaabbbccc’,lambda x:x.upper())for key,group in m:       print key,list[group] 返回:a ['a', 'a', 'a']b ['b', 'b', 'b']c ['c', 'c', 'c']takewhile(条件函数,构造队列)例如:n=itertools.count(1)ns=itertools.takewhile(lambda x:x<10,n)chain#将两个组联合例如:n=itertools.chain(‘abc’,’xyz’)imap:imap将两个队列按照公式组合例如:n=itertools.imap(lambda x,y:x*y,[2,3,5],itertools.count(3))for i in n:       print i两个队列如果不等长,以较短的为算.

2.6.15 解析xml

xml解析有两种方法,dom和sax.前者将文件一次读入内存,后者按照流来处理
用sax来处理首先定义一个类,定义以下函数
startelement
endelement
characterdata
然后引入parsercreate,将上面的函数赋给parsercreate,然后调用parser函数就可以解析xml了.

例如:

from xml.parsers.expat import ParserCreateclass DefaultSaxHandler(object):    def start_element(self, name, attrs):        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))    def end_element(self, name):        print('sax:end_element: %s' % name)    def char_data(self, text):        print('sax:char_data: %s' % text)xml = r'''<?xml version="1.0"?><ol>    <li><a href="/python">Python</a></li>    <li><a href="/ruby">Ruby</a></li></ol>'''handler = DefaultSaxHandler()parser = ParserCreate()parser.returns_unicode = Trueparser.StartElementHandler = handler.start_elementparser.EndElementHandler = handler.end_elementparser.CharacterDataHandler = handler.char_dataparser.Parse(xml)输出:sax:start_element: ol, attrs: {}sax:char_data: sax:char_data:     sax:start_element: li, attrs: {}sax:start_element: a, attrs: {u'href': u'/python'}sax:char_data: Pythonsax:end_element: asax:end_element: lisax:char_data: sax:char_data:     sax:start_element: li, attrs: {}sax:start_element: a, attrs: {u'href': u'/ruby'}sax:char_data: Rubysax:end_element: asax:end_element: lisax:char_data: sax:end_element: ol

2.6.16 解析html

解析html首先引入python中已经定义好的htmlparser
然后从html中派生类,并定义自己想要处理的函数
然后调用feed函数就可以处理html了.
调用feed函数可以不一次性输入全部html.
例子:

from HTMLParser import HTMLParserfrom htmlentitydefs import name2codepointclass MyHTMLParser(HTMLParser):    def handle_starttag(self, tag, attrs):        print('tag:<%s>' % tag)    def handle_endtag(self, tag):        print('endtag:</%s>' % tag)    def handle_startendtag(self, tag, attrs):        print('starttag:<%s/>' % tag)    def handle_data(self, data):        print('data:%s'%data)    def handle_comment(self, data):        print('comment:%s'%data)    def handle_entityref(self, name):        print('entityref:&%s;' % name)    def handle_charref(self, name):        print('charref:&#%s;' % name)parser = MyHTMLParser()parser.feed('<html><head></head><body><p>Some <a href=\"#\">html</a> tutorial...<br>END</p></body></html>')输出:tag:<html>tag:<head>endtag:</head>tag:<body>tag:<p>data:Some tag:<a>data:htmlendtag:</a>data: tutorial...tag:<br>data:ENDendtag:</p>endtag:</body>endtag:</html>

2.6.17 tcp函数

tcp函数与c中的socket函数差不多

import socket客户端s=spcket.socket(socket.AF_NET,socket.SOCK_STREAM)s.connect((‘url’,port))s.send(‘xxx’)s.recv(最大的数量)s.close()服务器:s=socket.socket(socket.AF_NET,socket.SOCK_STREAM)s.bind(‘0.0.0.0’,port)s.listen(等待连接的最大数)while True:       sock,addr=s.accept()       t=threading.Thread(target=tcplink,args=(sock,addr))       t.start()def tcplink(sock,addr):       sock.send(‘Welcome’)       data=sock.recv(maxdata)       time.sleep(1)

2.6.18 电子邮件:

需要两个模块:email和smtplib
email用来构造邮件,smtplib用来发送邮件

from email.mime.text import MIMETextmsg=MIMEText(‘正文’,’类型:可以是plain表示是文本’,’编码方式:可以是utf-8’)import smtplibserver=smtplib.SMTP(服务器地址,端口号)server.set_debuglevel(1)#显式调试信息server.login(from_addr,password)server.sendmail(from_addr,to_addr,msg.as_string())server.quit(()为了更完善邮件需要为msg加上from,to,subjectfrom email import encodersfrom email.header import Headerfrom email.mime.text import MIMETextfrom email.utils import parseaddr, formataddrimport smtplibdef _format_addr(s):    name, addr = parseaddr(s)    return formataddr(( \        Header(name, 'utf-8').encode(), \        addr.encode('utf-8') if isinstance(addr, unicode) else addr))from_addr = raw_input('From: ')password = raw_input('Password: ')to_addr = raw_input('To: ')smtp_server = raw_input('SMTP server: ')msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')msg['From'] = _format_addr(u'Python爱好者 <%s>' % from_addr)msg['To'] = _format_addr(u'管理员 <%s>' % to_addr)msg['Subject'] = Header(u'来自SMTP的问候……', 'utf-8').encode()server = smtplib.SMTP(smtp_server, 25)server.set_debuglevel(1)server.login(from_addr, password)server.sendmail(from_addr, [to_addr], msg.as_string())server.quit()

我们编写了一个函数_format_addr()来格式化一个邮件地址。注意不能简单地传入name addr@example.com,因为如果包含中文,需要通过Header对象进行编码。
msg[‘To’]接收的是字符串而不是list,如果有多个邮件地址,用,分隔即可。

2.6.19使用数据库

sqlite

import sqlite3conn=sqlite3.connect(‘xx.db’)#如果不存在,会自动创建cursor=conn.cursor()cursor.execute(‘sql语句’)cursor.rowcountcursor.fetchall()#返回结果是一个list,每个元素是一个tuple,对应一行记录cursor.close()cursor.commit()

mysql

mysql的使用与sqlite差不多

首先是建立连接,然后使用游标

# 导入MySQL驱动:>>> import mysql.connector# 注意把password设为你的root口令:>>> conn = mysql.connector.connect(user='root', password='password', database='test', use_unicode=True)>>> cursor = conn.cursor()# 创建user表:>>> cursor.execute('create table user (id varchar(20) primary key, name varchar(20))')# 插入一行记录,注意MySQL的占位符是%s:>>> cursor.execute('insert into user (id, name) values (%s, %s)', ['1', 'Michael'])>>> cursor.rowcount1# 提交事务:>>> conn.commit()>>> cursor.close()# 运行查询:>>> cursor = conn.cursor()>>> cursor.execute('select * from user where id = %s', ('1',))>>> values = cursor.fetchall()>>> values[(u'1', u'Michael')]# 关闭Cursor和Connection:>>> cursor.close()True

创建mysql的数据库:

mysqladmin  create数据库名 -u username -pmysqladmin drop 数据库名 -u username -p #删除数据库

2.6.20 使用sqlalchemy

象上面使用sql语句来操纵数据库比较繁琐,使用salalchemy的orm框架就可以避免直接使用sql语句,而可以使用类进行操作,减少代码量.
原理是先建立类,然后使用sqlalchemy来建立连接,此时创建一个session,然后用这个session来操纵数据库.
代码如下:

#! /usr/bin/python#-*- coding:utf-8 -*-# 导入:from sqlalchemy import Column, String, create_enginefrom sqlalchemy.orm import sessionmakerfrom sqlalchemy.ext.declarative import declarative_base# 创建对象的基类:Base = declarative_base()# 定义User对象:class User(Base):    # 表的名字:    __tablename__ = 'user'    # 表的结构:    id = Column(String(20), primary_key=True)    name = Column(String(20))# 初始化数据库连接:engine = create_engine('mysql+mysqlconnector://root:root@localhost:3306/test')# 创建DBSession类型:DBSession = sessionmaker(bind=engine)session=DBSession()input_id=raw_input('input id:')input_name=raw_input('input name:')new_user=User(id=input_id,name=input_name)session.add(new_user)session.commit()session.close()session=DBSession()user=session.query(User).all()for i in user:    print i.id,i.name

2.7web开发

2.7.1web协议:

当浏览网页时,先发送请求:get /http1.1host:网站地址get表示请求的方法,/表示根目录,http1.1表示协议类型还可以有post方法,后面跟一个body/路径 表示请求其他路径的文件返回:http/1.1 200 okcontent-type:text/htmlhttp/1.1 表示协议,200表示正常返回,其他数字3xx表示重定向,4xx表示发送端有错误,5xx表示服务端有错误.content-type:text/html表示文本类型.后面就是正文

实例:

请求:GET /wiki/001374738125095c955c1e6d8bb493182103fac9270762a000 HTTP/1.1Host: www.liaoxuefeng.comConnection: keep-aliveCache-Control: max-age=0User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.1 (KHTML, like Gecko) Ubuntu/12.04 Chromium/22.0.1201.0 Chrome/22.0.1201.0 Safari/537.1Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Encoding: gzip,deflate,sdchAccept-Language: zh-CN,zh;q=0.8Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3Cookie: Hm_lvt_2efddd14a5f2b304677462d06fb4f964=1466689703,1466821312,1466846745,1466862427; Hm_lpvt_2efddd14a5f2b304677462d06fb4f964=1466862427返回:HTTP/1.1 200 OKServer: nginx/1.1.19Date: Sat, 25 Jun 2016 13:48:09 GMTContent-Type: text/html; charset=utf-8Transfer-Encoding: chunkedConnection: keep-aliveX-Cluster-Node: liaoxuefeng-02X-Execution-Time: 13Content-Encoding: gzip

2.7.2html文件

通过上面的协议,客户端向服务端请求数据,服务端返回head之后,就是html正文了.

html由以下几部分构成:

<html>   <head>   一般有style样式,script脚本,link连接到css,meta提供页面信息,title标题   </head>   <body>   正文:包括<h1,2,..>标题   <p>段落   <tr>表格          </body></html>

浏览器通过样式来渲染正文.

css格式:

样式是用来渲染正文的,所在位置可以在head中,也可在正文中,原则是越靠近使用者,越有效.比如对于同样的样式名,在正文中就比在head中有效.

定义样式:

样式定义1:h1 {color:red;background-color:gray}样式定义2:类定义.my{color:red;background-color:gray}样式定义3:id定义#my{color:red;background-color:gray}使用样式:可以在任何<p>,<div>,<h>,<title>等元素中使用样式比如在标题中使用定义1:<h1>aaa</h1>在段落中使用定义2:<p class=”my”>aaa</p>在段落中使用定义3:<p id=”my”>aaa</p>

2.7.3web服务器

web服务器在python中可以使用wsgiref接口来开发,也可以使用框架比如flask.

下面分别用代码演示:

使用wsgiref接口:

#!/usr/bin/python#-*- coding:utf-8 -*-from wsgiref.simple_server import make_server,demo_appdef app(environ,start_response):    start_response('200 ok',[('Content-Type','text/html')])    return '<h1>Hello</h1>'httpd=make_server('',8000,app)print 'Serving http on port 8000'httpd.serve_forever()

使用flask框架

#!/usr/bin/python#-*- coding:utf-8 -*-from flask import Flaskfrom flask import requestfrom search import init,searchapp=Flask(__name__)head_str='''<head>    <title>Hello</title></head>'''@app.route('/',methods=['get','post'])def home():    return '<title>Home</title>'+'<h1>Hello</h1>'@app.route('/<path>')def path(path):    try:        body_str=head_str        res=search(path)        count=0        for i in res:            if count==0:                body_str=body_str+('<h3>%s</h3></hr>'%i)            else:                body_str=body_str+('<p>%s</p>'%i)            count=count+1        return '%s'%body_str    except:        return 'not found'if __name__=='__main__':    init()    app.run('0.0.0.0',8000)
0 0