学习python的日常6
错误、调试和测试:
错误处理:
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进程再去共享的磁盘上读取文件。
学习python的日常6的更多相关文章
- 学习python的日常
今天是开始正式接触python语言的第一天,然后来自前辈的知道开始了在学习过程当中用博客来记录自己的学习历程,以供自己更快地掌握这门编程语言. 大概的总结一下的话,还是按照我的编程的习惯,要学写代码, ...
- 学习python的日常7
---恢复内容开始--- 正则表达式: 在正则表达式中,用\d可以匹配一个数字,\w可以匹配一个字母或数字,'.'可以匹配任意字符,用*表示任意个字符,用+表示至少一个字符,用?表示0个货一个字符,用 ...
- 学习python的日常5
形如__xxx__的变量或者函数名,在python中是有特殊用途的,例如__slots__是为了绑定属性的名称, __len()__方法是为了让class作用于len()函数,很多这样的函数都可以帮忙 ...
- 学习python的日常4
偏函数: 偏函数是functools模块提供的一个功能,偏函数可以通过设定参数的默认值,降低函数调用的难度 其中设定的参数默认值实际上是可以被传入为其他值的,最后创建偏函数时可接收函数对象.*args ...
- 学习python的日常3
python的一些高级特性: 切片(跟名字一样,把一个完整的东西选取一部分自己想要的去切下来):通过切片可以快速的去除一些元素,只要确定好索引位置,避免的循环导致的多写代码 数组,元组,字符串都可以用 ...
- 学习python的日常2
---恢复内容开始--- 数组list 添加用.append(i,'xxx')方法 删除用.pop(i)方法,其中i为索引位置 数组可以直接作为元素插入数组 元组tuple(初始化后不能改变,所谓不变 ...
- D03——C语言基础学习PYTHON
C语言基础学习PYTHON——基础学习D03 20180804内容纲要: 1 函数的基本概念 2 函数的参数 3 函数的全局变量与局部变量 4 函数的返回值 5 递归函数 6 高阶函数 7 匿名函数 ...
- 人工智能时代,应立即学习python
人工智能时代,应立即学习python 应用:web开发,自动化运维开发,自动化测试,数据分析,机器学习 1.python 快速易学习2.python 基于web开发(zhihu:tornad web框 ...
- 国内某Python大神自创完整版,系统性学习Python
很多小伙伴纠结于这个一百天的时间,我觉得完全没有必要,也违背了我最初放这个大纲上来的初衷,我是觉得这个学习大纲还不错,自学按照这个来也能相对系统的学习知识,而不是零散细碎的知识最后无法整合,每个人的基 ...
随机推荐
- vue---数据列表过滤筛选
使用vue进行数据过滤筛选是比较常用的功能,常见的使用场景就是搜索框数据筛选过滤了.简单示例: <template> <div> <input type="te ...
- oracle的merge语法
merge into trade.ttradeseat ausing trade.bs_zrt_tradeseat bon (a.L_FUND_ID = b.l_Fund_Id and a.l_bas ...
- [LeetCode] 507. Perfect Number 完美数字
We define the Perfect Number is a positive integer that is equal to the sum of all its positive divi ...
- golang 基于channel封装资源池(可用于封装redis、mq连接池)
package pool import ( "errors" "io" "sync" "time" ) var ( Er ...
- 【电商日志项目之六】数据分析-Hive方式
环境 hadoop-2.6.5 hive-1.2.1 一.Hive和Hbase整合如果使用Hive进行分析,Hive要从Hbase取数据(当然可以直接将数据存到Hive),那么就需要将Hive和HBa ...
- java jdk 8u191 官网下载地址
目前jdk最后免费版本 jdk-8u191 下载地址: https://www.oracle.com/technetwork/java/javase/downloads/java-archive-ja ...
- LeetCode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)
82. 删除排序链表中的重复元素 II 82. Remove Duplicates from Sorted List II 题目描述 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有 ...
- 05 Mybatis的CRUD操作和Mybatis连接池
1.CRUD的含义 CRUD是指在做计算处理时的增加(Create).读取(Retrieve)(重新得到数据).更新(Update)和删除(Delete)几个单词的首字母简写.主要被用在描述软件系统中 ...
- springmvc数据的封装
spring封装是进行orm封装,可以进行定义数据类型,数据名与接收名相同,进行接收,或者定义类,类的属性名与接收名相同 单个数据类型如图下: 对象类型封装: 其他:乱码处理 在中文字符乱码,需要规定 ...
- Hive学习(2)
什么是hive Hive是基于Hadoop的一个数据仓库工具(E抽取T转换L加载),可以将结构化的数据文件映射为一张表,并提供类SQL查询功能 hive的处理流程 ()将HQL语句转化为一组操作符 ( ...