感觉已经差不多了,必须要实战下了,当时还是为了爬虫学的,现在发现搞数据挖掘也挺好/火
然而….还是等熟练了再说吧
最近好浮躁啊啊啊!!
错误/异常处理
有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
Py使用try...except...finally...
的错误处理机制,一个例子:
1 | try: |
当我们认为某些代码可能会出错时,就可以用try
来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except
语句块,执行完except
后,如果有finally
语句块,则执行finally
语句块,至此,执行完毕。
错误有时不会只有一个,所以可以使用多个except进行处理;所有的错误类型都继承自BaseException这个类
继承关系:https://docs.python.org/3/library/exceptions.html#exception-hierarchy
如果错误没有被捕获,它就会一直往上抛,最后被Python解释器捕获,打印一个错误信息,然后程序退出。
不过报错信息貌似是从下往上看,有点和其他不一样….(调用XX出错,在X行,原因是第X行 :雾)
另外一种形式:
1 | try: |
使用try except else
语句,当有异常是会执行except的语句,如果没有异常,则会执行else的语句
或者可以进行简写
1 | with xxx as f: |
xxx其实就是一个类,返回的值存在f中,可以是多个用元组就可以了,比如:open(xx)
,返回的是file对象,会自动进行关闭操作(无论是否发生了异常),不需要手动关闭
又叫做上下文管理器,执行时调用__enter__
方法,返回值存在f;退出时执行__exit__
方法(发生异常也执行)
记录错误
Python内置的logging模块可以非常容易地记录错误信息,主要代码:
1 | import logging |
同样是出错,但程序打印完错误信息后会继续执行,并正常退出。通过配置,logging还可以把错误记录到日志文件里,方便事后排查。
抛出异常
raise 主动抛出异常;格式:raise TypeError,"描述"
,或者抛一个异常对象:
1 | # 自定义异常 |
raise
语句如果不带参数,就会把当前异常原样抛出。此外,在except
中raise
一个Error,还可以把一种类型的异常转化成另一种类型
调试
assert 断言语句,一个简单的使用例子:assert 0==1 "描述"
会抛出一个assert异常,也就是说,如果后面的判断不成立就会抛出异常
启动Python解释器时可以用-O
参数来关闭assert:$ python3 -O err.py
;关闭后,你可以把所有的assert语句当成pass来看。
使用logging
和assert比,logging不会抛出错误,而且可以输出到文件;
它允许你指定记录信息的级别,有debug,info,warning,error等几个级别,当我们指定level=INFO
时,logging.debug
就不起作用了。同理,指定level=WARNING
后,debug和info就不起作用了。
是不是和某Log比较相似…
1 | import logging |
logging的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
pdb单步调试
其实就是单步调试,最好还是使用IDE
手动的话就是:$ python3 -m pdb err.py
输入命令l
来查看代码;
输入命令n
可以单步执行代码;
任何时候都可以输入命令p 变量名
来查看变量;
输入命令q
结束调试,退出程序
文件读写
读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
读文件
打开一个文件对象就是open("name","role")
,关于权限,常用的有这几种:
权限 | 描述 |
---|---|
r | 只读,文件必须存在,否则会抛异常 |
w | 只写,文件不存在时创建文件,存在则清空文件内容 |
a | 追加,文件不存在时创建文件 |
r+ | 打开文件会保持原文件内容不变,同样可以同时对文件进行读写,覆盖追加 |
w+ | 打开文件会将原文件内容删除,可以同时对文件进行读写 |
a+ | 追加和读写方式 |
rb,wb,ab,rb+,wb+,ab+ | 二进制方式打开(读取图片等) |
拿到文件对象后就可以进行读取内容了,可以使用read([size])
读取内容,也可以使用readline([size])
读取一行;使用readlines([size])
读取完缓冲区左右(io.DEFAULT_BUFFER_SIZE),返回每一行组成的列表.
最后一步是调用close()
方法关闭文件。文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的,但是有可能没有关闭之前出现了异常,所以最好放在try ... finally
里
可以直接使用for in
来读取file对象的每行的数据
file-like Object
像open()
函数返回的这种有个read()
方法的对象,在Python中统称为file-like Object。除了file外,还可以是内存的字节流,网络流,自定义流等等。file-like Object不要求从特定类继承,只要写个read()
方法就行。
StringIO
就是在内存中创建的file-like Object,常用作临时缓冲。
字符编码
要读取非UTF-8编码的文本文件,需要给open()
函数传入encoding参数,例如:open('./gbk.txt', 'r', encoding='gbk')
;如果遇到非法编码的字符,open()
函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:open('./gbk.txt', 'r', encoding='gbk', errors='ignore')
写入到文件
还是用的open这个函数,但是权限不同了,上面的表已经写的很明白了
你可以反复调用write()
来写入文件,但是务必要调用f.close()
来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()
方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()
的后果是数据可能只写了一部分到磁盘,剩下的丢失了。当然也可以使用flush进行刷新;所以,还是用with
语句来得保险:
1 | with open('/Users/michael/test.txt', 'w') as f: |
要写入特定编码的文本文件,请给open()
函数传入encoding
参数,将字符串自动转换成指定编码。
使用with语句操作文件IO是个好习惯。
文件指针
seek()
函数
接受2个参数:1.偏移量 2.相对偏移位置
file.tell()
返回文件的偏移
os.SEEK_SET:相对文件起始位置
os.SEEK_CUR:当前位置
os.SEEK_END:末尾位置
例子:f.seek(0,os.SEEK_SET)
:使文件指针回到开始位置;f.seek(-5,os.SEEK_CUR)
:从后向前移动5个字节f.seek(0,os.SEEK_END)
:将文件指针移到最后
文件属性
file.fileno() 文件描述符
.mode 文件打开权限
.closed 是否正确关闭
.enconding 编码方式文件标准输入:sys.stdin;
raw_input()该函数是从命令行接受输入,回车终止,可以传一个提示参数str
文件标准输出:sys.stdout;
文件标准错误:sys.stderr;sys模块提供sys.argv属性,通过该属性可以得到命令行参数;
sys.argv:字符串组成的列表,第一个参数多为文件名
codecs模块支持open指定编码
StringIO和BytesIO
很多时候,数据读写不一定是文件,也可以在内存中读写。
StringIO
StringIO顾名思义就是在内存中读写str。下面是个例子:
1 | from io import StringIO |
getvalue()
方法用于获得写入后的str。要读取StringIO,可以用一个str初始化StringIO,然后,像读文件一样读取:
1 | from io import StringIO |
BytesIO
StringIO操作的只能是str,如果要操作二进制数据,就需要使用BytesIO。
1 | from io import BytesIO |
请注意,写入的不是str,而是经过UTF-8编码的bytes。和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取.
OS模块
我们也是可以使用OS模块打开文件的(更贴近底层以及为了跨平台),有更多的方法,先把常用的方法列一下
os.open(filename, flag [,mode]):打开文件
flag打开方式:
os.O_CREAT:创建文件
os.O_RDONLY:只读方式打开
os.O_WRONLY:只写方式打开
os.O_RDWR:读写方式打开os.read(fd, buffersize):读取文件
os.write(fd, string):写入文件
os.lseek(fd, pos, how): 文件指针操作
os.close(fd):关闭文件os.access(path, mode): F_OK, R_OK ,W_OK, X_OK 判断是否有权限
os.listdir(path): 返回当path路径下所有文件名组成的列表
os.remove(path):删除文件
os.rename(old, new):修改文件或者目录名
os.mkdir(path[, mode]):创建目录
os.makedirs(path[, mode]):创建多级目录
os.removedirs(path):删除多级目录
os.rmdir(path):删除目录(目录必须空目录)os.path.exists(path):当前路径是否存在 | 也可以判断是否有该文件
os.path.isdir(s):是否是一个目录
os.path.isfile(path):是否是一个文件
os.path.getsize(filename):返回文件大小 | 返回目录文件大小
os.path.dirname(p):返回路径的目录
os.path.basename(p):返回路径的文件名
os.path.split():拆分出前面的路径和最好一级目录或文件
os.path.splitext():拆分文件后缀名os.name():系统类型 posix/nt
os.uname():查看系统信息
os.environ:环境变量(可以指定key比如:os.environ.get(‘PATH’))
序列化
Python提供了pickle模块来实现序列化。使用前注意Py的版本
1 | import pickle |
pickle.dumps()
方法把任意对象序列化成一个bytes
,然后,就可以把这个bytes
写入文件。或者用另一个方法pickle.dump()
直接把对象序列化后写入一个file-like Object.
当我们要把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()
方法反序列化出对象,也可以直接用pickle.load()
方法从一个file-like Object中直接反序列化出对象。
为了方便在不同语言间传递,我们一般序列化为XML或者JSON格式,JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
“string” | str |
1234.56 | int或float |
true/false | True/False |
null | None |
Python内置的json
模块提供了非常完善的Python对象到JSON格式的转换。
评论框加载失败,无法访问 Disqus
你可能需要魔法上网~~