错误、调试和测试:

错误处理:

try:
print('try...')
r = 10 / 0
print('result:', r)
except ZeroDivisionError as e:
print('except:', e)
finally:
print('finally...')
print('END')

 首先是执行语句,然后发现错误了就会跳转到执行except,语句,然后按顺序执行,如果是正确的就不会执行except语句。

其中的Error还可以细分,错误本身也是一个类,都继承自BaseException,所以尽量不要出现错误的父类和子类同时捕获,

因为这时候只会执行父类的捕获错误。

调用栈:

如果一个错误没有被捕获,就会一直往上抛,最后被python解释器捕获,出错的时候通过分析错误的调用栈信息,可以定位

错误的位置。

记录错误:

python内置的logging模块可以非常容易地记录错误信息

# err_logging.py

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()
print('END') $ python3 err_logging.py
ERROR:root:division by zero
Traceback (most recent call last):
File "err_logging.py", line 13, in main
bar('0')
File "err_logging.py", line 9, in bar
return foo(s) * 2
File "err_logging.py", line 6, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
END

抛出错误:

因为错误是class,然后捕获一个错误就是捕获到一个实例,如果要抛出错误,可以根据需要定义一个错误的class,

选择好继承关系,然后用raise语句抛出一个错误的实例。只有在必要的时候才定义我们自己的错误类型,如果可以,

尽量使用python内置的错误类型。

最后还有一种错误处理的方式:

# err_reraise.py

def foo(s):
n = int(s)
if n==0:
raise ValueError('invalid value: %s' % s)
return 10 / n def bar():
try:
foo('0')
except ValueError as e:
print('ValueError!')
raise bar()

 捕获异常后,又把错误用过raise语句抛出去,是因为,捕获错误的目的只是记录一下,由于当前函数不知道

应该怎么处理该错误,所以往上抛是一种很好的方式,最终会让顶层调用者去处理。

调试:

1.一种方法简单粗暴,直接用print()打印。

2.断言,凡是用print()来辅助查看的都可以用断言(assert)来替代。

3.logging,把print()替换为logging是第三种方式,logging可以指定记录信息的级别,有debug,info,warning,error

等几个级别,指定高级别的时候,低级别就不起作用了。

4.pdb,启用python的调试器pdb,让程序以单步方式运行,可以随时查看运行状态。pdb.set_trace(),也是用pdb,只

需要导入pdb,然后在可能出错的地方放一个pdb.set_trace(),就可以设置一个断点,到了之后就会暂停并进入pdb

调试环境,用p可以查看变量,用c继续运行。

5.IDE,支持调试功能的IDE,有一些比较好的Python IDE。

单元测试:

用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。我们给出一系列数据,然后期望输出的结果是我们

预期的结果,如果不相符就说明我们的代码中存在问题。

文档测试:

利用注释来告知代码我们希望得到的结果,然后又一些工具来自动生成文档。

IO编程:

IO指的是Input/Output,也就是输入和输出。IO编程中由于内外设备的速度不匹配,又可以分为同步IO和异步IO两种方式,

现在涉及到的是同步IO

文件读写:

读文件

>>> f = open('/Users/michael/test.txt', 'r')

 如果不存在就会报错,然后如果成功打开调用read()方法就可以一次性读到内存当中,用一个str对象表示,要记得调用

close()方法来关闭文件,如果出错是无法关闭文件的,f.close()也不会调用,所以用try...finally来实现,但是总写会很麻烦,

所以可以调用python的with语句来自动调用close()方法:

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

  想open()函数这种返回有个read()方法的对象,在python中统称为file-like Object,除了file外还有很多其他的流,不过只要

有个read()方法就可以了。读

>>> from io import StringIO
>>> f = StringIO()
>>> f.write('hello')
5
>>> f.write(' ')
1
>>> f.write('world!')
6
>>> print(f.getvalue())
hello world!

  操作二进制数据就需要使用BytesIO。

StringIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口。

取二进制文件,用’rb‘模式打开文件就行;读取字符编码文本文件,添加一个encoding=’gkb',遇到

不规范的可以添加参数errors=‘ignore'。

写文件

>>> f = open('/Users/michael/test.txt', 'w')
>>> f.write('Hello, world!')
>>> f.close()

 写文件和读文件一样,不过区别在于传入的标识符,‘w'或者’wb‘表示文本文件或者写二进制文件,如果要写入特定编码的文本

文件,要给open()传入encoding参数,将字符串自动转换成特定编码。

StringIO和BytesIO

操作文件和目录:

python的os模块封装了操作系统的目录和文件操作,这些函数有的在os模块中,有的在os.path模块中。

序列化:

把变量从内存中变成可存储或可传输的过程称之为序列化,反过来把变量内容从序列化的对象重新读到内存里称之为反序列化。

python提供pickle模块来实现序列化,但是要把序列变得更通用、更符合Web标准,就可以使用json模块。

json模块的dumps()和loads()函数是用来序列化和反序列化的,如果默认的序列化和反序列化机制不满足要求时,可以传入更多

的参数来定制序列化或反序列化规则。

进程和线程:

多任务的实现方式有3种:1.多进程模式;

2.多线程模式;

3.多进程+多线程模式

线程时最小的执行单元,而进程由至少一个线程组成。

多进程:

在Unix/Linux下,可以使用fork()调用实现多进程。

如果要实现跨平台的多进程,可以使用multiprocessing模块。

subprocess模块可以很方便地启动一个子进程,然后控制其输入和输出。

进程间通信时通过Queue、Pipes等实现地。

多线程:

同一个进程内多个线程,python地标准库提供了_thread和threading两个模块,绝大多数下使用threading这个高级模块。

启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行。多线程中,由于线程地调度是由系统

决定地,当线程交替执行时,很容易造成内容被乱改。为了确保变量,可以给线程上锁,一个进程提供一个锁,然后让

线程去获取该锁,这样线程就只有在获得锁的情况下才能执行语句,就不会造成冲突了。然后坏处的话只要时降低了

效率以及容易造成死锁。Python的解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,

必须先获得GIL锁。这个GIL全局锁实际上把所有线程的执行代码都给上锁。

ThreadLocal:

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')
t1.start()
t2.start()
t1.join()
t2.join()

  

局部变量在函数调用时很麻烦,一层一层传递很麻烦,全局变量local_school就是一个ThreadLocal对象,每个Thread

对它都可以读写student属性,但互不影响。可以把local_school看成全局变量,每个属性如local_school.student都是线

程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。

ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调

用到的处理函数都可以非常方便地访问这些资源。一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己

线程的独立副本,互不干扰。ThreadLocal解决了参数在一个线程中各个函数都可以非常方便地访问这些资源。

分布式进程:

Python地分布式进程接口简单,封装良好,适合需要把繁重任务分布到多台机器地环境下。

注意Queue地作用是用来传递任务和接收结果,每个任务的描述数据量要尽量小。比如发送一个处理日志文件的任务,

就不要发送几百兆的日志文件本身,而是发送日志文件存放的完整路径,由Worker进程再去共享的磁盘上读取文件。

最新文章

  1. C#开发微信门户及应用(16)-微信企业号的配置和使用
  2. 微信蓝牙设备开发教程之获取设备deviceid和二维码(3)
  3. github如何查看提交历史呢
  4. 用H5的canvas做时钟
  5. vue 倒计时
  6. Memcached入门
  7. Ubuntu10.10的网络配置
  8. UVA 11796 - Dog Distance
  9. HDU2015校赛 The Country List
  10. mongodb基础系列——数据库查询数据返回前台JSP(一)
  11. readn、write、readline
  12. Emacs颜色设置
  13. C#2.0--集合--转载车老师
  14. Mycat安装与使用
  15. FPGA两种寄存器的使能
  16. lamp环境搭建经验总结
  17. MiseringThread.java 解析页面线程
  18. txt文件按行处理工具类(可以截取小说、分析日志等)【我】
  19. LabVIEW--使用云端编译器编译多个vi
  20. 337A

热门文章

  1. Firefox 浏览器的长期支持版本(Firefox ESR)
  2. JVM常用命令和性能调优建议
  3. 不规则形状的Ifc构件顶点坐标获取
  4. Java8 Collectors类的静态工厂方法
  5. JVM 线上故障排查基本操作--内容问题排查
  6. [LeetCode] 67. Add Binary 二进制数相加
  7. Consul ACL集群配置说明以及ACL Token的用法
  8. spring_boot实战日记(二)logback的使用和配置
  9. linux awk的用法
  10. jQuery的基础总结