Python详细学习笔记+总结 第四天

错误、调试、测试
错误-1,成功0
try...except...finally

try:
    r = 10 / int('0')
except ValueError as e:
    print('ValueError:', e)
except ZeroDivisionError as e:
    print('ZeroDivisionError:', e)
else:
    print(r)
finally:
    print('finally')
ZeroDivisionError: division by zero
finally



继承BaseException

调用堆栈

记录错误
logging

import logging
def foo(s):
    return 10 / int(s)
def bar(s):
    return foo(s) * 2
def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)
main()



日志输出到文件

import logging
logging.basicConfig(filename='D:/py/root.log', filemode='a', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug('debug log')
logging.info('info log')
logging.warning('warning log')
2017-12-27 20:12:30,805 - DEBUG - debug log
2017-12-27 20:12:30,805 - INFO - info log
2017-12-27 20:12:30,805 - WARNING - warning log
debug、info、warning、error



抛出错误
自定义错误

class FooError(ValueError):
    pass
def foo(s):
    n = int(s)
    if n == 0:
        raise FooError('invalid value: %s' % s)
    return 10 / n
foo('0')



调试Debug
print()

断言assert

def foo(s):
    n = int(s)
    assert n != 0
    return 10 / n
def main():
    foo('0')

断言失败
AssertionError

pdb

pdb.set_trace()



单元测试
测试一个模块、一个函数、一个类

文档测试
doctest

IO编程
Stream 流
流为水管,数据为水,单向流动

同步IO、异步IO

文件读写
读文件

try:
    f = open('D:/py/root.log', 'r')
    print(f.read())
finally:
    if f:
        f.close()
with open('D:/py/root.log', 'r', encoding='utf-8') as f:
    print(f.read())



r、w文本文件,rb二进制文件

read 一次读取全部
read(size)
readline 读取一行
readlines 读取所有行

写文件

f = open('D:/py/root.log', 'w')
f.write('Hello, World!')
f.close()
with open('D:/py/root.log', 'w') as f:
    f.write('Hello, World!')



w 写文件
wb 写二进制文件

StringIO
在内存中读写str

from io import StringIO
f = StringIO()
f.write('hello')
f.write(' ')
f.write('world!')
print(f.getvalue())
hello world!
from io import StringIO
f = StringIO('Hello!
Hi!
Goodbye!')
while True:
    s = f.readline()
    if s == '':
        break
    print(s.strip())
Hello!
Hi!
Goodbye!



BytesIO
内存中读写bytes

操作文件和目录
os 调用系统命令

import os
os.name
nt
os.uname() 报错
os.environ
os.path.abspath('.')
C:\Windows



创建目录

os.path.join('D:', 'py')
os.mkdir('D:/py/test')
os.rmdir('D:/py/test')



路径

os.path.join()
os.path.split()
os.rename()
os.remove()
s = 'D:/py/root.log'
os.path.split(s)
('D:/py', 'root.log')



序列化 pickle
存储、传输
转为二进制

import pickle
d = dict(name='Bob', age=20, score=96)
pickle.dumps(d)



写入文本

f = open('D:/py/dump.txt', 'wb')
pickle.dump(d, f)
f.close()



读取

f = open('D:/py/dump.txt', 'rb')
d = pickle.load(f)
f.close()
{'name': 'Bob', 'age': 20, 'score': 96}



JSON
不同语言之间传递数据
序列化标准格式
JavaScript语言的对象

import json
json_str = '{"name":"Bob", "age":20, "score":88}'
json.loads(json_str)
{'name': 'Bob', 'age': 20, 'score': 88}



进程和线程
进程 程序运行的最小单位
线程 进程子任务
一个进程,至少有一个线程
区别 线程共享数据
多任务 多进程、多线程、多进程+多线程

multiprocessing
start 启动进程
join 进程间同步

from multiprocessing import Process
import os
import time
def run_proc(name):
    time.sleep(3)
    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',))
    p.start()
    p.join()
    print('child process stop')
Parent process 3868.
run child process test (5384)
child process stop



Pool 进程池

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 run %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,))
    p.close()
    p.join()
    print('all subprocesses done.')
parent process 5124.
run task 1 (5028)
task 1 run 0.92 seconds.
run task 2 (5028)
task 2 run 0.39 seconds.
run task 0 (4632)
task 0 run 2.73 seconds.
all subprocesses done.



进程间通信
交换数据

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)
def read(q):
    print('process to read %s' % os.getpid())
    for v in range(3):
        value = q.get()
        print('get %s form queue.' % value)
if __name__ == '__main__':
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    pw.start()
    pr.start()
    pw.join()
    pr.terminate() #强行终止
process to write: 4640
put A to queue...
put B to queue...
put C to queue...
process to read 5552
get A form queue.
get B form queue.
get C form queue.



多线程
是真正的线程

_thread 低级模块
threading 高级模块
MainThread 主线程
current_thread() 当前线程



Lock
包含锁的代码,单线程执行

import time, threading
balance = 0
lock = threading.Lock()
def change_it(n):
    global balance
    balance = balance + n
    balance = balance - n
def run_thread(n): #结果为0
    for i in range(1000000):
        lock.acquire() #获取锁
        try:
            change_it(n)
        finally:
            lock.release() #释放锁
def run_thread(n): #结果随机
    for i in range(1000000):
        change_it(n)
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))    
t1.start()
t2.start()
t2.join()
t1.join()
print(balance)



多核CPU
GIL全局锁
多线程交替执行,单核

ThreadLocal
创建与线程名称关联的局部变量
为线程绑定一个数据库连接、HTTP请求、用户信息

import threading
local_school = threading.local()
def process_student():
    std = local_school.student
    print('Hello, %s (in %s)' % (std, threading.current_thread().name))
def process_thread(name):
    local_school.student = name
    process_student()
t1 = threading.Thread(target=process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target=process_thread, args=('Lily',), name='Thread-B')
t1.start()
t2.start()
t2.join()
t1.join()
Hello, Alice (in Thread-A)
Hello, Lily (in Thread-B)



进程 VS 线程
Master-Worker模式
Master分配任务
Worker执行任务
一个Master,多个Worker

多进程模式
稳定性高
开销大

多线程模式

不稳定

某个线程出现问题
该程序执行了非法操作,即将关闭

计算密集型 VS IO密集型
计算密集型
视频解码
消耗CPU C语言
同时进行任务数量 = CPU核心数

IO密集型
网络、磁盘读写、Web应用
任务越多,CPU效率越高

异步IO
事件驱动模型 单线程支持多任务
Nginx 支持异步IO

协程
单进程的异步编程模型

分布式进程
managers
把多进程分布到多台机器,依靠网络通信

上一篇:Mybatis批量操作配置文件UserMapper.xml

下一篇:Python详细学习笔记+总结 第三天