PHP and Python学习

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.html
http://www.w3school.com.cn/index.html

1.3基本语法

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

"#! /usr/bin/php
<?php
print “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,else
if(expr) {
statement}
else{
statement}
替换写法:
if expr:
elseif:
endif

switch
switch expr{
case condition1:
statemen1 ;
break;
}

循环

for;foreach,while
for(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/python
print “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 codecs
with codecs.open(xxxfilename,’rb’,’utf8’) as f
  str=f.read()
就可以避免在str中再做转换了.

codecs支持的编码如下:

编码别名支持语言
ascii646, us-asciiEnglish
big5big5-tw, csbig5Traditional Chinese
big5hkscsbig5-hkscs, hkscsTraditional Chinese
cp037IBM037, IBM039English
cp424EBCDIC-CP-HE, IBM424Hebrew
cp437437, IBM437English
cp500EBCDIC-CP-BE, EBCDIC-CP-CH, IBM500Western Europe
cp720Arabic
cp737Greek
cp775IBM775Baltic languages
cp850850, IBM850Western Europe
cp852852, IBM852Central and Eastern Europe
cp855855, IBM855Bulgarian, Byelorussian, Macedonian, Russian, Serbian
cp856Hebrew
cp857857, IBM857Turkish
cp858858, IBM858Western Europe
cp860860, IBM860Portuguese
cp861861, CP-IS, IBM861Icelandic
cp862862, IBM862Hebrew
cp863863, IBM863Canadian
cp864IBM864Arabic
cp865865, IBM865Danish, Norwegian
cp866866, IBM866Russian
cp869869, CP-GR, IBM869Greek
cp874Thai
cp875Greek
cp932932, ms932, mskanji, ms-kanjiJapanese
cp949949, ms949, uhcKorean
cp950950, ms950Traditional Chinese
cp1006
cp1026ibm1026Turkish
cp1140ibm1140Western Europe
cp1250windows-1250Central and Eastern Europe
cp1251windows-1251Bulgarian, Byelorussian, Macedonian, Russian, Serbian
cp1252windows-1252Western Europe
cp1253windows-1253Greek
cp1254windows-1254Turkish
cp1255windows-1255Hebrew
cp1256windows-1256Arabic
cp1257windows-1257Baltic languages
cp1258windows-1258Vietnamese
euc_jpeucjp, ujis, u-jisJapanese
euc_jis_2004jisx0213, eucjis2004Japanese
euc_jisx0213eucjisx0213Japanese
euc_kreuckr, korean, ksc5601, ks_c-5601, ks_c-5601-1987, ksx1001, ks_x-1001Korean
gb2312chinese, csiso58gb231280, euc- cn, euccn, eucgb2312-cn, gb2312-1980, gb2312-80, iso- ir-58Simplified Chinese
gbk936, cp936, ms936Unified Chinese
gb18030gb18030-2000Unified Chinese
hzhzgb, hz-gb, hz-gb-2312Simplified Chinese
iso2022_jpcsiso2022jp, iso2022jp, iso-2022-jpJapanese
iso2022_jp_1iso2022jp-1, iso-2022-jp-1Japanese
iso2022_jp_2iso2022jp-2, iso-2022-jp-2Japanese, Korean, Simplified Chinese, Western Europe, Greek
iso2022_jp_2004iso2022jp-2004, iso-2022-jp-2004Japanese
iso2022_jp_3iso2022jp-3, iso-2022-jp-3Japanese
iso2022_jp_extiso2022jp-ext, iso-2022-jp-extJapanese
iso2022_krcsiso2022kr, iso2022kr, iso-2022-krKorean
latin_1iso-8859-1, iso8859-1, 8859, cp819, latin, latin1, L1West Europe
iso8859_2iso-8859-2, latin2, L2Central and Eastern Europe
iso8859_3iso-8859-3, latin3, L3Esperanto, Maltese
iso8859_4iso-8859-4, latin4, L4Baltic languages
iso8859_5iso-8859-5, cyrillicBulgarian, Byelorussian, Macedonian, Russian, Serbian
iso8859_6iso-8859-6, arabicArabic
iso8859_7iso-8859-7, greek, greek8Greek
iso8859_8iso-8859-8, hebrewHebrew
iso8859_9iso-8859-9, latin5, L5Turkish
iso8859_10iso-8859-10, latin6, L6Nordic languages
iso8859_11iso-8859-11, thaiThai languages
iso8859_13iso-8859-13, latin7, L7Baltic languages
iso8859_14iso-8859-14, latin8, L8Celtic languages
iso8859_15iso-8859-15, latin9, L9Western Europe
iso8859_16iso-8859-16, latin10, L10South-Eastern Europe
johabcp1361, ms1361Korean
koi8_rRussian
koi8_uUkrainian
mac_cyrillicmaccyrillicBulgarian, Byelorussian, Macedonian, Russian, Serbian
mac_greekmacgreekGreek
mac_icelandmacicelandIcelandic
mac_latin2maclatin2, maccentraleuropeCentral and Eastern Europe
mac_romanmacromanWestern Europe
mac_turkishmacturkishTurkish
ptcp154csptcp154, pt154, cp154, cyrillic-asianKazakh
shift_jiscsshiftjis, shiftjis, sjis, s_jisJapanese
shift_jis_2004shiftjis2004, sjis_2004, sjis2004Japanese
shift_jisx0213shiftjisx0213, sjisx0213, s_jisx0213Japanese
utf_32U32, utf32all languages
utf_32_beUTF-32BEall languages
utf_32_leUTF-32LEall languages
utf_16U16,utf16all languages
utf_16_beUTF-16BEall languages (BMP only)
utf_16_leUTF-16LEall languages (BMP only)
utf_7U7, unicode-1-1-utf-7all languages
utf_8U8, UTF, utf8all languages
utf_8_sigall languages

base64编码

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

模块有base64

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

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

数据转换

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

import struct
struct.pack(‘转换格式’,数据字符串)   #将数据字符串转换成二进制数据
struct.unpack(‘转换格式’,二进制字符串)    #将二进制字符串转换成数据
例如:struct.pack(‘h’,1024)    #将1024按照2字节的小头序转换(低字节在前)
输出:/x00/x04
struct(‘>h’,1024)   #将1024按照2字节的大头序(网络次序)转换(高字节在前)
输出:/x04/0x00
struct.unpack(‘h’,’/x00/x04’)
输出:1024
转换字符:i表示按照4字节转换整数,h表示按照2字节转换整数,>表示按照大头序,不带>表示按照小头序转换.
FormatC TypePython typeStandard sizeNotes
ccharchar11
bsignedchar integer1(3)
Bunsigned charinteger1(3)
?Boolbool1(1)
hshortinteger2(3)
Hunsigned shortinteger2(3)
iintinteger4(3)
Iunsigned intinteger4(3)
llonginteger4(3)
Lunsigned longinteger4(3)
qlong longinteger8(2), (3)
Qunsigned long longinteger8(2), (3)
ffloatfloat4(4)
ddoublefloat8(4)
schar[]string
pchar[]string
Pvoid *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/python
def yang():
        u=[1]
        while True:
                yield u
                u.append(0)
                u=[u[i]+u[i-1] for i in range(len(u))]
j=0
for 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 collections
dd=defaultdict(lambda:’N/A’)
dd[‘a’]=1
dd[‘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 Counter
ch=Counter()
for i in str:
  ch[i]=ch[i]+1
counter返回的是一个dict{‘xx’:xx,’xx’:xx...}#注意,访问dict对象是通过key来访问的xxdict.[关键字]
Counter构造函数输入的是一个list,Counter.most_common(排名前几位)返回的是排名前几位的list对象.
例子:搜索文章中排名前10位的单词
from collections import Counter
import re
words=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=b
b=a+b

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

2.3.5 控制

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

if expr :
    statement
else
    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 MethodType
class student(object):
       __slots__=('name','age','add_fun')
s=student();
s.name='han'
s.age=32
print s.name,s.age
def 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_fun
s2.add_fun('a')
getattr
getattr可以在类中没有需要的成员时,返回一个默认的成员值
       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=value

s=screen()
s.width=19
print 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#引入loggng
logging.basicConfig(level=logging.INFO)#设置logging级别debug,info,warning,error
class 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 unittest
from test import MyList
class 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.py
Run:
start
E
teardown

======================================================================
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.000s

FAILED (errors=1)

2.6 函数

2.6.1 函数定义

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

2.6.2 引入其他模块:

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

2.6.3 map和reduce函数

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

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

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

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

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

2.6.4 filter 函数

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

def f(x):
    return x%2==0
l=filter(f,range(10))
print l
Run:[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 str2
Run:
 [('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_fun
s=f(1,2,3)  #此时不会返回结果
s()  #此时才会返回结果
相当于是函数指针.
Run:6

2.6.7 匿名函數:

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

Y=lambda x:x*x
Y(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 codecs
codecs.open()
f.close()#关闭文件
如果不想每次都关闭文件可以用:
with open as f 
    f.xxx

2.6.10 os模块:

os模块中封装了系统命令

import os
os.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 pickle
p=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 json
j=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的dict
Json对象的[]对应python的list
上面讲的的是对dict对象进行序列化,如果需要对类进行序列化,需要对类进行加工.
class strudent:
       def __init__(self,name,age,scope):
           self._name=name
           self._age=age
           self.scope=scope
def student2dict(std):#需要将类转换成json的dict
       return{‘name’:std.name,’age’:std.age,’scope’:std.scope}
s=student(‘bog’,28,1)
import json
json.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 os
pid=os.fork()
if pid==0:
       print (‘i\’m a child process’)
else:
       print (‘i\’m a parent process’)
或者:
from multiprocessing import Process
import os
def 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,threading
def 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,Queue
from multiprocessing.managers import BaseManager
task_queue=Queue.Queue()
result_queue=Queue.Queue()
class QueueManager(BaseManager):
    pass
QueueManager.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 ,Queue
from multiprocessing.managers import BaseManager
class QueueManager(BaseManager):
    pass
QueueManager.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,调用函数是match
import re
re.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)是010
m.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 m
print m.group()
word=re.findall(re_words,s)
上面的程序曾经出现没有找到匹配中文的情况,是由于字符串编码没有采用unicode.

2.6.13 hashlib

用来计算散列值

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

2.6.14 itertools

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

import itertools
n=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 ParserCreate

class 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 = True
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
parser.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: Python
sax:end_element: a
sax:end_element: li
sax:char_data: 

sax:char_data:     
sax:start_element: li, attrs: {}
sax:start_element: a, attrs: {u'href': u'/ruby'}
sax:char_data: Ruby
sax:end_element: a
sax:end_element: li
sax:char_data: 

sax:end_element: ol

2.6.16 解析html

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

from HTMLParser import HTMLParser
from htmlentitydefs import name2codepoint

class 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:html
endtag:</a>
data: tutorial...
tag:<br>
data:END
endtag:</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 MIMEText
msg=MIMEText(‘正文’,’类型:可以是plain表示是文本’,’编码方式:可以是utf-8’)
import smtplib
server=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,subject
from email import encoders
from email.header import Headerfrom email.mime.text 
import MIMETextfrom email.utils 
import parseaddr, formataddrimport smtplib
def _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 sqlite3
conn=sqlite3.connect(‘xx.db’)#如果不存在,会自动创建
cursor=conn.cursor()
cursor.execute(‘sql语句’)
cursor.rowcount
cursor.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.rowcount
1
# 提交事务:
>>> 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 -p
mysqladmin 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_engine
from sqlalchemy.orm import sessionmaker
from 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.1
host:网站地址
get表示请求的方法,/表示根目录,http1.1表示协议类型
还可以有post方法,后面跟一个body
/路径 表示请求其他路径的文件
返回:
http/1.1 200 ok
content-type:text/html
http/1.1 表示协议,200表示正常返回,
其他数字3xx表示重定向,4xx表示发送端有错误,5xx表示服务端有错误.
content-type:text/html表示文本类型.

后面就是正文

实例:

请求:
GET /wiki/001374738125095c955c1e6d8bb493182103fac9270762a000 HTTP/1.1
Host: www.liaoxuefeng.com
Connection: keep-alive
Cache-Control: max-age=0
User-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.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding: gzip,deflate,sdch
Accept-Language: zh-CN,zh;q=0.8
Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3
Cookie: Hm_lvt_2efddd14a5f2b304677462d06fb4f964=1466689703,1466821312,1466846745,1466862427; 
Hm_lpvt_2efddd14a5f2b304677462d06fb4f964=1466862427
返回:
HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Sat, 25 Jun 2016 13:48:09 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Cluster-Node: liaoxuefeng-02
X-Execution-Time: 13
Content-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_app
def 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 Flask
from flask import request
from search import init,search
app=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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值