异常处理
报错格式及顺序
try:
print("try报错 就匹配执行except类型,没有则报错,Exception指定所有报错")
except Exception as e:
print(e)
else:
print("如果try没报错,执行else")
finally:
print("无论执行try或else 最后都执行finally")
简单实例
#输入1或0
try:
s = 1
if s is 0:
#print("%s 是错误的"%s)
raise NameError("%s 是错误的"%s) #如果引发NameError异常,后面的代码将不能执行
print(len(s))
except TypeError:
print("%s 是错误的" % s)
实例
#捕获出错后,提示异常信息,且不退出,捕获错误可多个
#Exception捕获所有错误,写其他错误类型就是捕获具体错误类型,写一种类型加一个except
#输入字符串 提示报错并继续
while True:
num1 = input("请输入第一位数字:")
num2 = input("请输入第二位数字:")
try:
num1 = int(num1)
num2 = int(num2)
result = num1 + num2
exit("%s + %s = %s"%(num1,num1,result))
except NameError as e:
#捕获具体错误,后操作如下,报错重要性可写入log,也可忽略,print("出现异常,信息如下:")
print(e)
except Exception as e:
#捕获所有错误print("出现异常,信息如下:")
print(e)
#invalid literal for int() with base 10: 'asfd' 这是说第10行输入不是int类型
主动错误模式
try:
raise Exception('错误了。。。')
except Exception as e:
print(e)
#错误了。。。
自定义异常模式
class guolm(Exception): #创建类 传参是Exception(所有报错)
def __init__(self,msg):
self.message = msg
def __str__(self):
return self.message
try:
raise guolm("我的异常") #主动异常
except guolm as e:
print(e)
#我的异常
断言
assert 1 == 1 #条件满足则继续
assert 1 == 2 #条件不满足则报错
错误类型
python2.x捕获异常语法:
try:
...some functions...
except Exception, e:
print(e)
python3.x捕获异常语法:
try:
...some functions...
except Exception as e:
print(e)
注意这里 Exception, e 变成了 Exception as e
python常见的异常类型
0.
Exception 捕获所有错误1. NameError: 尝试访问一个未申明的变量
>>> v
NameError: name 'v' is not defined
2. ZeroDivisionError: 除数为0
>>> v = 1/0
ZeroDivisionError: int division or modulo by zero
3. SyntaxError: 语法错误
int int
SyntaxError: invalid syntax (<pyshell#14>, line 1)
4. IndexError: 索引超出范围
List = [2]
>>> List[3]
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
List[3]
IndexError: list index out of range
5. KeyError: 字典关键字不存在,
试图访问字典里不存在的键Dic = {'1':'yes', '2':'no'}
>>> Dic['3']
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
Dic['3']
KeyError: '3'
6. IOError: 输入输出错误:
基本上是无法打开文件>>> f = open('abc')
IOError: [Errno 2] No such file or directory: 'abc'
7. AttributeError: 访问未知对象属性
>>> class Worker:
def Work():
print("I am working")
>>> w = Worker()
>>> w.a
Traceback (most recent call last):
File "<pyshell#51>", line 1, in <module>
w.a
AttributeError: 'Worker' object has no attribute 'a'
8.ValueError: 数值错误
>>> int('d')
Traceback (most recent call last):
File "<pyshell#54>", line 1, in <module>
int('d')
ValueError: invalid literal for int() with base 10: 'd'
9. TypeError: 类型错误
>>> iStr = '22'
>>> iVal = 22
>>> obj = iStr + iVal;
Traceback (most recent call last):
File "<pyshell#68>", line 1, in <module>
obj = iStr + iVal;
TypeError: Can't convert 'int' object to str implicitly
- 10. AssertionError: 断言错误
>>> assert 1 != 1
Traceback (most recent call last):
File "<pyshell#70>", line 1, in <module>
assert 1 != 1
AssertionError
11. MemoryError: 内存耗尽异常
12.ImportError 无法引入模块或包;基本上是路径问题或名称错误
13.IndentationError 语法错误(的子类) ;代码没有正确对齐
14.KeyboardInterrupt Ctrl+C被按下 15.UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它
16. NotImplementedError: 方法没实现引起的异常
class Base(object):
def __init__(self):
pass
def action(self):
#抛出异常,说明该接口方法未实现
raise NotImplementedError
- 17. LookupError: 键、值不存在引发的异常
LookupError异常是IndexError、KeyError的基类, 如果你不确定数据类型是字典还是列表时,可以用LookupError捕获此异常
18. StandardError 标准异常
除StopIteration, GeneratorExit, KeyboardInterrupt 和SystemExit外,其他异常都是StandarError的子类。
错误检测与异常处理区别在于:错误检测是在正常的程序流中,处理不可预见问题的代码,例如一个调用操作未能成功结束
更多错误
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
更多异常
socket
#socket 讲解 http://www.cnblogs.com/alex3714/articles/5227251.html
# 武老师 http://www.cnblogs.com/wupeiqi/articles/5040823.html
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #获取tcp/ip套接字
#phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #获取udp/ip套接字
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #防止端口结束不释放
phone.bind(('127.0.0.1',8010)) #绑定服务端ip+端口
phone.listen(5) #监听最大连接数为5
phone.setblocking(bool) #是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错
phone.accept()
#conn,client_addr=phone.accept() #conn是建立连接(具体跟某个用户的连接通信),client_addr是客户端访问的ip+port
#接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。
#接收TCP 客户的连接(阻塞式)等待连接的到来
phone.connect(('127.0.0.1',8080)) #连接server服务的ip+port 连接请求
phone.close() #关闭连接
phone.recv(1024) #一次接受数据大小
sk.recvfrom(bufsize[.flag]) #和recv一样,只是多了从哪里接受的数据地址
sk.send(string[,flag]) #发送数据 所有通信(整个手机的通信)
sk.sendall(string[,flag]) #发送所有数据
sk.sendto(string[,flag],address) #和send功能一样 但需要指定远程地址,一半不用
sk.settimeout(timeout) #超时时间 连接远程机器 多长时间超时
sk.getpeername() #返回远程地址 返回值通常是元组(ipaddr,port)
sk.getsockname() #返回本机地址。通常是一个元组(ipaddr,port)
sk.fileno() #套接字的文件描述符
socket.sendfile(file, offset=0, count=None) #发送文件 ,但目前多数情况下并无什么卵用
socket实现简单通信
运行方式先启动server在启动client
server端
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #获取tcp/ip套接字 socket.AF_INET家庭模式 socket.SOCK_STREAM通讯方式是tcp
#phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 获取udp/ip套接字
server.bind(("127.0.0.1",8000)) #绑定服务端ip+port
server.listen(5) #最大监听连接数为5
conn,client_addr=server.accept() #接受用户连接并返回数据
#conn是建立连接(具体跟某个用户的连接通信,当前连接的用户),client_addr是客户端访问的ip+port
print(conn,client_addr)
while True:
data=conn.recv(1024) #1024是字节 #一次接收数据最大值
print("rece",data)
conn.send(b"got your msg") #发送数据,conn.send()发送数据给正在连接的conn用户
client端
import socket
client=socket.socket() #固定连接
client.connect(("127.0.0.1",8000)) #指定服务端ip+port
while True: #指定循环发送数据
msg= input(">>>").strip()
if len(msg)==0:continue #用户输入不为空
client.send(msg.encode()) #发送byte类型数据
#client.send(b"hello") #python只能发bite数据,encode()默认是byte类型
print("send",msg)
data=client.recv(1024) #接受单次数据最大值1024字节
print("receive from server:",data)
socket实现简单通信 ,多个用户交互连接不中断
server端
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#获取tcp/ip套接字 socket.AF_INET家庭模式 socket.SOCK_STREAM通讯方式是tcp
#phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)获取udp/ip套接字
server.bind(("127.0.0.1",8000)) #绑定服务端ip+port
server.listen(5) #最大监听连接数为5
while True: #当前用户断开,下一个用户连接正常接入
conn,client_addr=server.accept() #接受用户连接并返回数据
#conn是建立连接(具体跟某个用户的连接通信,当前连接的用户),client_addr是客户端访问的ip+port
print(conn,client_addr)
while True: #用于用户多次交互
try:
data=conn.recv(1024) #1024是字节 #一次接收数据最大值
print("rece",data)
conn.send(b"got your msg") #发送数据,conn.send()发送数据给正在连接的conn用户
except Exception: #因为client断开会影响server端 特加异常处理
#conn.close() #这个不需要加 会自动释放
break
client
看第一次client配置 (这次配置2个用户,)
执行方式 先开启服务器 在开启client端(2个)
粘包
socket 模拟ssh登录
执行方式 先启动server 再启动client
server端
import socket
import subprocess
server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",8300)) #绑定服务端ip+port
server.listen(5) #最大监听连接数为5
while True: #当前用户断开,下一个用户连接正常接入
conn,client_addr=server.accept() #接受用户连接并返回数据
print(conn,client_addr)
while True: #用于用户多次交互
data=conn.recv(1024) #1024是字节 #一次接收数据最大值
print("rece",data)
res_obj= subprocess.Popen(data, shell=True, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
res= res_obj.stdout.read() #读取成功日志
conn.send(str(len(res)).encode()) #len转成str并变成byte格式
print("---res len---",len(res),str(len(res)).encode())
conn.send(res) #发送数据
client端
import socket
client=socket.socket() #固定连接
client.connect(("127.0.0.1",8300)) #指定服务端ip+port
while True: #指定循环发送数据
msg= input(">>>").strip()
if len(msg)==0:continue #用户输入不为空
client.send(msg.encode()) #发送byte类型数据
data=client.recv(1024) #接受单次数据最大值1024字节
total_size = int(data.decode())
received_size = 0
res = b'' #定义byte格式
while received_size < total_size: #total_size是server端发送的数据,如果不为执行如下
d = client.recv(1024) #每次接受1024,
res += d
received_size += len(d) #received_size == total_size后,说明接受完毕,结束循环
print("--------end----------------------------")
print(res.decode()) #解密显示数据
服务器端
import socket
#获取tcp/ip套接字
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #获取tcp/ip套接字
#phone = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 获取udp/ip套接字
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #防止端口结束不释放
phone.bind(('127.0.0.1',8010)) #绑定服务端ip+端口
phone.listen(5) #最大连接数
print('server start...')
while True: #链接循环
conn,client_addr=phone.accept()
print(conn,client_addr)
while True: #通讯循环
try:
client_data=conn.recv(1024) #接受数据
if not client_data:break #针对linux系统
conn.send(client_data.upper()) #发送数据 #sedall 发送所有数据
#
except Exception: #针对windwos
break
conn.close() #这是客户端链接断开
phone.close() #这是服务端断开
#socket.SOCK_STREAM #流式协议,基于tcp协议
#socket.SOCK_DGRAM #udp协议 数据报协议
#bind内写元祖 ,内学本机ip+port
#phone.listen(5) 最大挂起连接数为5
#conn.recv(1024) 收发消息 最大接受限制1024
#conn 是socket记录信息
#<socket.socket fd=4, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080), raddr=('127.0.0.1', 60617)>
#client_addr 是客户端访问的ip+port,('127.0.0.1', 60617)
client端 可以多个
import socket
phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))
while True:
msg=input('>>: ').strip()
if not msg:continue
phone.send(msg.encode('utf-8'))
# print('====>has send')
server_data=phone.recv(1024)
# print('====>has recv')
print(server_data.decode('utf-8'))
phone.close()
python解决办法
phone=socket(AF_INET,SOCK_STREAM)
phone.setsockopt(SOL_SOCKET,SO_REUSEADDR,1) #就是它,在bind前加
phone.bind(('127.0.0.1',8080))
linux解决办法
发现系统存在大量TIME_WAIT状态的连接,通过调整linux内核参数解决,
vi /etc/sysctl.conf
编辑文件,加入以下内容:
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_fin_timeout = 30
然后执行 /sbin/sysctl -p 让参数生效。
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
net.ipv4.tcp_fin_timeout 修改系統默认的 TIMEOUT 时间