Kahn's blogs

Python3学习笔记

2018/06/29

Python3学习笔记

本篇为学习廖老师的Python3教程所做的摘要笔记。有一些自己写归纳的东西,一直在完善中。

安装篇

  1. mac上自带的python是2.x的,先装上3.x再说。
  2. brew install python3
  3. brew link python

    • 大概率会出现如下错误

      1
      2
      Error: Could not symlink lib/pkgconfig/python-3.6.pc
      /usr/local/lib/pkgconfig is not writable.
    • 总之就是没权限

      1
      sudo chown -R $USER /usr/local/lib/

      得到权限后,在重试link命令,如果遇到Frameworks目录不存在,或者没有权限之类的。在使用如下命令

      1
      2
      sudo mkdir /usr/local/Frameworks
      sudo chown -R $(whoami) $(brew --prefix)/*
* 此时再去link一下

基础语法

字符串

1
2
3
4
5
chr(66)输出66的字符形式
ord与上面相反
格式化
>>> "%s,%s" % ('aaa','bbb')
'aaa,bbb'

list,tuple

list
声明一个数组:list = [‘xxxx’, True, 123]
append,insert,pop可以操作数组。可以使用list[-1] 取出list中最后一个。以此类推

tuple
不可变的list:tuple = (‘xxx’, 123)
注意 当只有一个元素的tuple时,使用逗号消除歧义。应这样声明tuple = (‘xxx’, )

条件判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
第一种:
if <条件判断>:
...
else:
...
第二种:
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>

字符串不能和int型比较,需要用int()函数转换

循环

for…in… 和while

1
2
3
4
5
6
7
8
9
10
11
12
# for...in..
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print(name)
# while
sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print(sum)

dict和set

1
2
3
4
5
6
7
8
# dict(其实就是map,键值对)
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
d['Tracy'] = 67
# 使用'Thomas' in d判断是否存在key
# set定义
s = set([1, 2, 3])

函数

官方文档

使用help(函数名) 查询函数用法

定义

1
2
3
4
abstest.py
def test(x):
return xxx;

使用from abstest import my_abs引入函数调用

关键字pass 什么也不做

1
2
if test > 10:
pass

检查类型

1
2
3
4
5
6
7
def test(x):
if not isinstance(x, (int, float)):
raise TypeError('bad operand type')
if x >= 0:
return x
else:
return -x

返回多个值

1
2
3
4
5
6
7
def test(x):
return x1,x2
>>> value = test(2)
这个value是一个tuple。
也可以这么写:
>>> x1,x2 = test(2)

参数默认值

1
def test(x, y = 2)

可变参

1
2
3
4
5
6
7
def calc(*test):
相当于java中的...
调用时如果参数是个list,可以直接使用*展开
calc(*list)

关键字参数

1
2
3
4
5
def test(test1, test2, **kw)
kw接受一个dict键值对
比如
test(x,x,key=value, key=value)

关键字参数命名检查

1
2
3
4
5
6
7
8
9
# 自我检查
def person(name, age, **kw):
if 'city' in kw:
# 有city参数
pass
if 'job' in kw:
# 有job参数
pass
print('name:', name, 'age:', age, 'other:', kw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
如果要限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字参数。这种方式定义的函数如下:
def person(name, age, *, city, job):
print(name, age, city, job)
使用*隔开。
如果中间有一个可变参,就不要写额外的*了 例如
def person(name, age, *args, city, job):
print(name, age, city, job)
调用时一定要写参数名,
# 调用
person('Jack', 24, city='Beijing', job='Engineer')

参数组合

参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

1
2
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

切面取值

有一个list值为[0, 1, 2, 3, …, 99]
取出前10个list[0:10],0如果是第一个,可以省略
前10个数,每3个取一个,list[0:10:3],
list[:] 原样copy出一个数组

迭代

默认情况下,dict迭代的是key,for key in d:。如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items()。
可以使用isinstance(‘abc’, Iterable)判断该对象能不能迭代。

迭代中的下标

1
2
3
4
5
6
>>> for i, value in enumerate(['A', 'B', 'C']):
... print(i, value)
...
0 A
1 B
2 C

上面的for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:

1
2
3
4
5
6
>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
... print(x, y)
...
1 1
2 4
3 9

列表生成器

1
2
3
4
5
[x * x for x in range(1, 11) if x % 2 == 0]
x * x 是结果。中间for...in是迭代。后面的if x % 2 == 0是条件。相当于java的list.filter((x) => x %2 == 0).map((x) => x * x);
[m + n for m in 'ABC' for n in 'XYZ']
多维度组合,这个还是比较有用的,使用了两个迭代生成的新的list

上面的列表生成器直接生成一个list对象。使用()可以产生一个generator,动态的计算下一个元素,而不是全部塞在内存里。

1
2
3
g = (x * x for x in range(10))
next(g) //使用next读取元素
for n in g: //使用迭代读取元素

一个函数中出现yield关键字,那么这个函数的返回值是一个generator,每一次的next都执行到yield返回的地方。只到抛出异常。for…in方式不抛出异常。所以读不到最后的return的值

迭代器

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的

1
2
isinstance([], Iterable) 判断是不是Iterable
isinstance([], Iterator) 判断是不是Iterator

函数式编程

map,reduce,filter,sorted

闭包

返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

匿名函数

lambda x: x * x,冒号前面的x是参数,后面是表达式。

装饰器

函数也是一个对象,所以,函数也有自己的属性,例如name就是函数名
如果想动态更改一个函数的行为,可以使用装饰器语法。
装饰器本质上是一个高阶函数,它接收目标函数,然后做一些事情后,再返回目标函数的引用。

1
2
3
4
5
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper

这个例子,log函数接收一个函数参数func。返回一个函数引用wrapper,在wrapper内先打印了func名字,后执行了func。
如果我们执行目标函数的地方都改为log(目标函数),那么执行目标函数前都会打印目标函数的名字。
python为我们提供了语法支持

1
2
3
@log
def now():
print('2015-3-25')

相当于

1
now = log(now)

下面是一个完整的例子,带参数,带copy函数属性

1
2
3
4
5
6
7
8
9
10
import functools
def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

偏函数 functools.partial

1
2
3
4
5
6
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85

functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

重构时会非常有用。

使用模块

非常简单 import

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
' a test module '
__author__ = 'kahn'
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello,World!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
test()

安装第三方库

官方插件库

先查找好库名,然后使用pip install xxx 安装

综合插件库anaconda

面向对象编程

语法

class Test(object):
后面括号为继承自哪个类

声明变量

test = Test()

可以给对象附加属性,例如,test.param1 = ‘testxxx’

定义类的初始变量

1
2
3
4
5
class Test(object):
def __init__(self, param1, param2):
self.param1 = param1
self.param1 = param2

生成对象时,第一个参数self忽略。

定义类的方法

1
2
3
4
5
6
7
8
class Test(object):
def __init__(self, param1, param2):
self.param1 = param1
self.param1 = param2
def testMethod(self):
print(self.param1);

注意:定义类的方法,第一次参数一定要是self,self为当前对象的实例,调用时无需传入

定义私有变量

1
2
3
4
5
class Test(object):
def __init__(self, param1, param2):
self.__param1 = param1
self.__param1 = param2

在成员变量前加两个下划线就是私有成员变量,外部不可访问

继承,多态

class Test(object)就是继承了。

在子类中可以覆盖父类的方法。

和java不同的一点。如果一个方法接收一个对象,它只使用了这个对象的test方法。那么,传入对象的类型可以是不固定的,只要有test方法就可以了。

isinstance(b, Test) 判断对象类型

对象的信息

type方法

1
2
3
4
5
6
7
8
9
10
11
12
获取对象信息
>>> type(123)
<class 'int'>
做比较
>>> import types
>>> type(123)==type(456)
True
>>> type(123)==int
True
>>> type(fn)==types.FunctionType
True

isinstances方法

1
2
3
类型还可以传多个
>>> isinstance([1, 2, 3], (list, tuple))
True

dir()方法,获取对象的属性及方法,此外还有getattr()、setattr()以及hasattr(),都是进行属性方法操作的。

类属性

1
2
class Test(object):
name = 'Test'

在类外给类附加方法

附加在对象上的方法,只本对象有效

1
2
3
4
5
6
7
8
>>> def set_age(self, age): # 定义一个函数作为实例方法
... self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25

附加类方法

1
2
3
4
>>> def set_score(self, score):
... self.score = score
...
>>> Student.set_score = set_score

限制附加属性

1
2
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

使用@property使外部可以方便访问变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Person(object):
def __init__(self, name, height):
self.__name = name
self.__height = height
@property
def name(self):
return self.__name
@name.setter
def name(self, name):
self.__name = name
@property
def height(self):
return self.__height
def test():
person = Person("kahn", 180)
print(person.name)
print(person.height)
person.name = 'xxx'
print(person.name)
if __name__=='__main__':
test()

多继承

1
class Dog(Mammal, Runnable):

类的特殊字段方法

__slots__ 限制
__str__ 相当于toString __repr__ 开发者模式的toString。 可以这样__repr__ = __str__
_iter__和__next__ ,第一个返回一个迭代对象,使用迭代对象会调用该对象的__next__
__getitem__ 像数组一样获取数据
__getattr__ 如果找不到属性,该方法将会触发
__call__ 把对象变为直接可调用 callable()来判断该对象是不是可调用的

枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
//这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员:
//遍历
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
//扩展,自定义value。(默认枚举的值为从1开始赋值)
//@unique装饰器可以帮助我们检查保证没有重复值。
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6

元类

使用type的方式动态创建类

1
2
3
4
>>> def fn(self, name='world'): # 先定义函数
... print('Hello, %s.' % name)
...
>>> Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class

metaclass

相当于使用代码动态构建类,具体还请看这边

错误、调试和测试

异常

python的try catch语法

1
2
3
4
5
6
7
8
9
10
11
12
13
try:
print('try...')
r = 10 / int('2')
print('result:', r)
except ValueError as e:
print('ValueError:', e)
except ZeroDivisionError as e:
print('ZeroDivisionError:', e)
else:
print('no error!')
finally:
print('finally...')
print('END')

Python所有的错误都是从BaseException类派生的 常见异常类

记录异常

使用 import logging logging.exception(e)

抛出异常

使用raise FooError('invalid value: %s' % s)

调试

断言语法

assert n != 0, 'n is zero!'

启动Python解释器时可以用-O参数来关闭assert

logging

import logging
logging.basicConfig(level=logging.INFO)
s = ‘0’
n = int(s)
logging.info(‘n = %d’ % n)
print(10 / n)

pdb 调试器

启动调试器
python -m pdb err.py

单元测试

单测写法

测试方法必须以test开头

1
2
3
4
5
6
7
8
9
10
11
12
//引入单测
import unittest
//引入要测试的类
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEqual(d.a, 1)
self.assertEqual(d.b, 'test')
self.assertTrue(isinstance(d, dict))

执行命令

$ python -m unittest mydict_test

setUp与tearDown

和java一样,同样有这两个方法

写法

1
2
3
4
5
6
7
class TestDict(unittest.TestCase):
def setUp(self):
print('setUp...')
def tearDown(self):
print('tearDown...')

文档测试

在文档中也可按固定格式写出测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def abs(n):
'''
Function to get absolute value of number.
Example:
>>> abs(1)
1
>>> abs(-1)
1
>>> abs(0)
0
'''
return n if n >= 0 else (-n)

IO

文件读写

打开文件

第二个参数是模式,r表示读一个文本,rb表示读一个二进制

1
>>> f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

关闭流

第一种,try finally

1
2
3
4
5
6
7
try:
f = open('/path/to/file', 'r')
print(f.read())
finally:
if f:
f.close()

第二种 with语法

1
2
3
with open('/path/to/file', 'r') as f:
print(f.read())

read() 读取全部
read(size) 读取固定字节
readlines() 读取一行

write() 默认‘w’是覆盖,‘a’追加

StringIO和BytesIO

StringIO 在内存中读写字符串

1
2
3
4
5
6
7
8
9
10
>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!

BytesIO 在内存中读写byte字节

1
2
3
4
5
6
>>> from io import BytesIO
>>> f = BytesIO()
>>> f.write('中文'.encode('utf-8'))
6
>>> print(f.getvalue())
b'\xe4\xb8\xad\xe6\x96\x87'

OS扩展包(操作文件和目录)

引入OS

1
2
3
>>> import os
>>> os.name # 操作系统类型
'posix'

os.environ获取所有环境变量,os.environ.get(‘key’)获取具体某个环境变量

操作文件和目录

基本操作

1
2
3
4
5
6
7
8
9
10
# 查看当前目录的绝对路径:
>>> os.path.abspath('.')
'/Users/michael'
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
>>> os.path.join('/Users/michael', 'testdir')
'/Users/michael/testdir'
# 然后创建一个目录:
>>> os.mkdir('/Users/michael/testdir')
# 删掉一个目录:
>>> os.rmdir('/Users/michael/testdir')

split

1
2
3
4
5
>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
>>> os.path.splitext('/path/to/file.txt')
('/path/to/file', '.txt')

shutil模块提供了copyfile()的函数,你还可以在shutil模块中找到很多实用函数,它们可以看做是os模块的补充

实例:

1
2
3
4
5
6
7
列出当前目录下的所有目录
>>> [x for x in os.listdir('.') if os.path.isdir(x)]
['.lein', '.local', '.m2', '.npm', '.ssh', '.Trash', '.vim', 'Applications', 'Desktop', ...]
列出所有的.py文件
>>> [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
['apis.py', 'config.py', 'models.py', 'pymonitor.py', 'test_db.py', 'urls.py', 'wsgiapp.py']

序列化

pickle模块的序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
dumps 用法
>>> import pickle
>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)
dump用法
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
反序列化
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}

json模块的序列化

1
2
3
4
5
6
7
8
9
10
序列化
>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
反序列化
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}

定制json序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def student2dict(std):
return {
'name': std.name,
'age': std.age,
'score': std.score
}
>>> print(json.dumps(s, default=student2dict))
{"age": 20, "name": "Bob", "score": 88}
def dict2student(d):
return Student(d['name'], d['age'], d['score'])
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x10cd3c190>

进程和线程

进程

os.fork() 创建一个子进程,该方法在父进程和子进程中都会返回值

multiprocessing模块Process类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
p.start()
p.join()
print('Child process end.')

multiprocessing模块Pool类 进程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')

对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了

subprocess模块

1
2
3
4
5
6
import subprocess
print('$ nslookup www.python.org')
r = subprocess.call(['nslookup', 'www.python.org'])
print('Exit code:', r)

进程间通信

Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from multiprocessing import Process, Queue
import os, time, random
# 写数据进程执行的代码:
def write(q):
print('Process to write: %s' % os.getpid())
for value in ['A', 'B', 'C']:
print('Put %s to queue...' % value)
q.put(value)
time.sleep(random.random())
# 读数据进程执行的代码:
def read(q):
print('Process to read: %s' % os.getpid())
while True:
value = q.get(True)
print('Get %s from queue.' % value)
if __name__=='__main__':
# 父进程创建Queue,并传给各个子进程:
q = Queue()
pw = Process(target=write, args=(q,))
pr = Process(target=read, args=(q,))
# 启动子进程pw,写入:
pw.start()
# 启动子进程pr,读取:
pr.start()
# 等待pw结束:
pw.join()
# pr进程里是死循环,无法等待其结束,只能强行终止:
pr.terminate()

线程

ython的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import time, threading
# 新线程执行的代码:
def loop():
print('thread %s is running...' % threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('thread %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' % threading.current_thread().name)
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)

加锁

1
2
3
4
5
6
7
8
9
10
11
lock = threading.Lock()
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()

ThreadLocal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import threading
# 创建全局ThreadLocal对象:
local_school = threading.local()
def process_student():
# 获取当前线程关联的student:
std = local_school.student
print('Hello, %s (in %s)' % (std, threading.current_thread().name))
def process_thread(name):
# 绑定ThreadLocal的student:
local_school.student = name
process_student()
t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')

分布式进程

1
2
import random, time, queue
from multiprocessing.managers import BaseManager

具体看教程

正则表达式

re模块中含有正则表达式所有的方法

1
2
3
s = 'ABC\\-001' # Python的字符串
s = r'ABC\-001' # Python的字符串 前面+r可以省去转译\

match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None。常见的判断方法就是:

1
2
3
4
5
test = '用户输入的字符串'
if re.match(r'正则表达式', test):
print('ok')
else:
print('failed')

编译正则,以便重复使用

1
2
3
4
5
6
7
8
>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')

常用内置api

datetime

1
from datetime import datetime

collections

1
2
3
4
5
namedtuple
deque
defaultdict
OrderedDict
Counter

struct

用来处理基本数据类型和byte之间的转换

1
2
>>> import struct
>>> struct.pack('>I', 10240099)

hashlib

一些hash算法

contextlib

对with语法的解析

urllib

提供一些访问url的方法

get

1
2
3
4
5
6
7
8
9
from urllib import request
req = request.Request('http://www.douban.com/')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
with request.urlopen(req) as f:
print('Status:', f.status, f.reason)
for k, v in f.getheaders():
print('%s: %s' % (k, v))
print('Data:', f.read().decode('utf-8'))

post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from urllib import request, parse
print('Login to weibo.cn...')
email = input('Email: ')
passwd = input('Password: ')
login_data = parse.urlencode([
('username', email),
('password', passwd),
('entry', 'mweibo'),
('client_id', ''),
('savestate', '1'),
('ec', ''),
('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F')
])
req = request.Request('https://passport.weibo.cn/sso/login')
req.add_header('Origin', 'https://passport.weibo.cn')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F')
with request.urlopen(req, data=login_data.encode('utf-8')) as f:
print('Status:', f.status, f.reason)
for k, v in f.getheaders():
print('%s: %s' % (k, v))
print('Data:', f.read().decode('utf-8'))

Web开发

1
2
3
4
5
6
7
8
9
10
11
12
13
#application.py
def application(environ, start_response):
start_response('200 ok', [('Content-Type', 'text/html')])
return [b'<h1>hello web</h1>']
#server.py
from wsgiref.simple_server import make_server
from web.application import application
httpd = make_server('', 8080, application)
print('Server Http on port 8080...')
httpd.serve_forever()

异步io

1
2
3
4
5
6
7
8
9
10
11
12
13
import threading
import asyncio
@asyncio.coroutine
def hello():
print('Hello world! (%s)' % threading.currentThread())
yield from asyncio.sleep(1)
print('Hello again! (%s)' % threading.currentThread())
loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

新老用法

1
2
3
4
5
6
7
8
9
10
11
12
@asyncio.coroutine
def hello():
print("Hello world!")
r = yield from asyncio.sleep(1)
print("Hello again!")
async def hello():
print("Hello world!")
r = await asyncio.sleep(1)
print("Hello again!")

注意新语法只能用在Python 3.5以及后续版本