python异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-3
异常捕获
异常:程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来
影响:整个程序无法再正常运行
异常的结构
异常的类型
NameError
异常的信息
name 'safaf' is not defined
异常的位置
'''
Traceback (most recent call last):
File "E:/PyCharm 2019.1.3/ProjectFile/day010/day029/01 异常处理.py", line 1, in <module>
safaf
'''
异常的种类
语法错误
程序错误编译成一般都会直接有提示,提示就应该直接解决的,出现语法错误一般是基础太差。
逻辑错误
这种错误是可以被容忍的,逻辑错误无法一眼看出来
针对逻辑上的错误可以采用异常处理机制来进行捕获
常见的错误类型
常见的出错类型 | 原因 |
---|---|
NameError | 名字错误 |
SyntaxError | 语法错误 |
keyError | 键不存在 |
ValueError | 值错误 |
IndexError | 索引错误 |
如何避免
异常处理
使用:在你认为可能会出现问题的代码上方用 try 包起来
注意:try 内部的代码块越少越好
异常处理能少用就少用,不然该报错的不报错哪里错了你都不知道
像服务端、客户端断开链接就需要用到异常处理,你不知道他什么时候会断开
异常处理使用模板(try.. except.. else.. finally..)
try:
可能出错的代码
except 出错类型 as e: # 将报错信息赋值给e
错误的处理代码
except 出错类型2 as e: # 将报错信息赋值给e
错误的处理代码
except 出错类型3 as e: # 将报错信息赋值给e
错误的处理代码
# 或者 Exception直接捕获所有的
except Exception as e: # 可以匹配所有的错误类型
BaseException 是 Exception 的父类,也可以捕获所有类型
错误的处理代码
else:
当被检测的代码没有任何异常发生,才会执行这里面的语句
finally:
无论被检测的代码有没有异常发生,都会在代码执行完后执行这里面的代码
案例
try:
safaf
except NameError as e:
print(e)
else:
print("没有报错才会执行我哦~")
finally:
print("管你报不报错,我都会执行的!")
# name 'safaf' is not defined
# 管你报不报错,我都会执行的!
try:
print("我没错哦~")
except Exception as e: # 捕捉所有异常
print("管你啥错,我都抓了!")
else:
print("没有报错才会执行我哦~")
finally:
print("管你报不报错,我都会执行的!")
# 我没错哦~
# 没有报错才会执行我哦~
# 管你报不报错,我都会执行的!
补充
出错后会立即停止代码运行,去与except中的错误类型一个个比较,匹配上了就执行里面的代码,没匹配上就直接报错
主动抛出异常raise
if 'egon' == 'DSB':
pass
else:
raise TypeError('尽说大实话') # 这一行就是报错的位置
# raise 关键字就是用来主动抛出异常的
断言assert
断言不成立直接报错
l = [1, 2, 3]
assert len(1) < 0 # assert 断言,预言,猜某个数据的状态,猜对了不影响代码执行,猜错了直接报错
自定义异常(继承异常类)
报错类型,其实对应的就是一个个类(可以自定义拼接异常的格式)
class MyError(BaseException):
def __init__(self, msg):
super().__init__()
self.msg = msg
def __str__(self):
return f'----<{self.msg}>----'
raise MyError('自定义的异常')
# Traceback (most recent call last):
# File "E:/PyCharm 2019.1.3/ProjectFile/day010/day029/test.py", line 15, in <module>
# raise MyError('自定义的异常')
# __main__.MyError: ----<自定义的异常>----
UDP通信
UDP协议又叫用户数据报协议
它没有双向通道,类似于发短信(只管发,不管对方有没有收到,不需要对方立即回应)
UDP的程序可以先启动客户端再启动服务端(客户端发数据给服务端之前都没问题)
UDP类似于发短信
TCP类似于打电话,你一句我一句的
普通使用
服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM) # type=socket.SOCK_DGRAM 指定成 UDP 协议 type=socket.SOCK_STREAM TCP协议(默认就是,不用指定)
server.bind(('127.0.0.1', 8080))
# UDP 不需要设置半连接池(server.listen(5)),也没有半连接池的概念
# UDP 没有双向通道,所以也不需要建立连接(conn, addr = server.accept())
# 直接就是通信循环
while True: # 这里只需要直接通信(交互)即可
data, addr = server.recvfrom(1024)
print("数据:", data.decode('utf-8')) # 客户端发来的消息
print("地址:", addr) # 客户端的地址
re_msg = input("Please input your response msg:").strip() # 会阻塞在这里,这里过了,才能发出信息,看到下一条信息
server.sendto(re_msg.encode('utf-8'), addr) # 向客户端发送消息
# 数据: hi
# 地址: ('127.0.0.1', 64821)
# Please input your response msg:o hi
# 数据: hihihi
# 地址: ('127.0.0.1', 64823)
# Please input your response msg:xxixixi
# 数据: aha e
# 地址: ('127.0.0.1', 64828)
# Please input your response msg:emmm?
# 数据:
# 地址: ('127.0.0.1', 64828)
# Please input your response msg:adsa
客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
# UDP 不需要建立连接(client.connect(('127.0.0.1', 8080)))
server_addr = ('127.0.0.1', 8080) # UDP sendto发消息时需要一个服务器的地址及端口号
while True:
msg = input("Please input your msg:").strip()
client.sendto(msg.encode('utf-8'), server_addr) # 向服务器发送数据,要附带服务器端地址及端口(基于网络传输的数据都必须是二进制的)
data, msg_from_server_addr = client.recvfrom(1024) # 收到消息,且得到地址
print("服务端发来的数据:", data.decode('utf-8'))
print("服务器端的ip及端口", msg_from_server_addr)
# 窗口1
# Please input your msg:hi
# 服务端发来的数据: o hi
# 服务器端的ip及端口 ('127.0.0.1', 8080)
# Please input your msg:
# 窗口2
# Please input your msg:hihihi
# 服务端发来的数据: xxixixi
# 服务器端的ip及端口 ('127.0.0.1', 8080)
# Please input your msg:
# 窗口3
# Please input your msg:aha e
#
# 服务端发来的数据: emmm?
# 服务器端的ip及端口 ('127.0.0.1', 8080)
# Please input your msg:服务端发来的数据: adsa
# 服务器端的ip及端口 ('127.0.0.1', 8080)
# Please input your msg:
TCP与UDP之间的区别
- UDP 允许发空数据,不会有影响
- UDP 直接启动客户端未启动服务端不会报错
- UDP 不会有粘包问题(自带报头)
- UDP 支持并发
服务端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
data, addr = server.recvfrom(1024)
print(data.decode('utf-8'))
server.sendto(data.upper(), addr)
客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
while True:
msg = input(">>>:")
# -------------------------------------------
# 1.UDP 允许发空数据,不会有影响
# -------------------------------------------
# UDP自带报头,就算数据为空,另一端也能处理
client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080)) # 第二参数,目标服务器地址
# -------------------------------------------
# 2.UDP 直接启动客户端未启动服务端不会报错
# 发数据找不到服务端也还是会报错
# -------------------------------------------
# 下面两行代码直接注释掉,服务端没启动,都不会报错,只管给服务器发(收没收到不管)
# data, server_addr = client.recvfrom(1024)
# print(data)
# -------------------------------------------
# 3.UDP 不会有粘包问题(自带报头)
# -------------------------------------------
# client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
# client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
# client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8080))
#
# server.sendto(data.upper(), addr)
# server.sendto(data.upper(), addr)
# server.sendto(data.upper(), addr)
# -------------------------------------------
# 4.UDP 支持并发
# TCP是保持连接,而UDP不需要保持连接
# 与一个客户端断开连接才会和下一个客户端建立连接
# -------------------------------------------
简易版的QQ
服务器端
import socket
server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8080))
while True:
data, client_addr = server.recvfrom(1024)
print(data.decode('utf-8'))
msg = input(">>>:").strip()
server.sendto(msg.encode('utf-8'), client_addr)
# 来自star3的消息:helo
# >>>:hi
# 来自star2的消息:aha
# >>>:haa
# 来自star的消息:hello world
# >>>:ha
# 来自star2的消息:jason nnn
# >>>:jj
客户端1、2、3共用同一份代码
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
username = 'star' # 客户端对应改成 star2 star3
server_address = ('127.0.0.1', 8080) # 指定一个发消息的目标服务器
while True:
msg = input(">>>:").strip()
msg = f'来自{username}的消息:{msg}' # 是哪个用户名发出的数据不应该由这里传过去,用户可以随便改,实际意义不大
'''
user_dict = {
"username1": (ip1 + port1),
"username2": (ip2 + port2),
"username3": (ip3 + port3),
}
# 可以在每个端都存这样一个对照表,根据ip与port就可以知道用户名了
'''
client.sendto(msg.encode('utf-8'), server_address)
data, server_addr = client.recvfrom(1024) # server_addr 收到消息的服务端地址
print(data.decode('utf-8'))
# 各个窗口的控制台输入与输出
# >>>:helo
# hi
# >>>:
# >>>:aha
# haa
# >>>:jason nnn
# jj
# >>>:
# >>>:hello world
# ha
# >>>:
概念科普
- 并发
看起来像同时运行(直接启动多个UDP客户端)(默认的UDP程序多开就是这个效果)
- 并行
真正意义上的同时运行
socketserver模块科普
是给服务端用的(客户端还是用socket模块),能够支持服务端的并发
TCP模拟UDP实现并发
服务器端
import socketserver # 文件名不要和模块冲突了,不然都不知道导哪个了
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
# 与客户端进行通信
# print("来啦 老弟")
while True: # 需要保持通信(后续 client.send() 可没有附带服务器地址, connect 被关闭了)
data = self.request.recv(1024)
print(self.client_address) # 客户端地址
print(data.decode('utf-8'))
self.request.send(data.upper())
if __name__ == '__main__':
'''只要有客户端连接,会自动交给自定义类中的handle方法去处理'''
server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer) # 创建一个基于TCP的对象
server.serve_forever() # 启动该服务对象
# ('127.0.0.1', 14327)
# dAddA
# ('127.0.0.1', 14326)
# ADD
# ('127.0.0.1', 14325)
# ADsafga
客户端
# TCP 实现UDP
import socket
client = socket.socket()
client.connect(('127.0.0.1', 8080))
while True:
res = input(">>>:")
client.send(res.encode('utf-8'))
data = client.recv(1024)
print(data.decode('utf-8'))
# 窗口1 控制台数据(输入与输出)
# >>>:dAddA
# DADDA
# >>>:
# 窗口2 控制台数据(输入与输出)
# >>>:ADD
# ADD
# >>>:
# 窗口1 控制台数据(输入与输出)
# >>>:ADsafga
# ADSAFGA
# >>>:
socketserver之UDP
服务器端
import socketserver # 文件名不要和模块冲突了,不然都不知道导哪个了
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
# 与客户端进行通信
# while True: # UDP 不需要通信循环,每次 sendto 都有服务器的地址
data, sock = self.request
print(self.client_address) # 客户端地址
print(data.decode('utf-8'))
sock.sendto(data.lower(), self.client_address)
if __name__ == '__main__':
'''只要有客户端连接,会自动交给自定义类中的handle方法去处理'''
server = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyServer) # 创建一个基于UDP的对象
server.serve_forever() # 启动该服务对象
# 控制台打印的数据
# ('127.0.0.1', 52524)
# CLient2
# ('127.0.0.1', 52529)
# clet1
# ('127.0.0.1', 52529)
# CLienT1
# ('127.0.0.1', 54485)
# CLiEnt3
客户端
import socket
client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 8080)
while True:
res = input(">>>:").strip()
client.sendto(res.encode('utf-8'), server_addr)
data, response_server_addr = client.recvfrom(1024)
print(data.decode('utf-8'), response_server_addr)
# 窗口1 控制台数据(输入与输出)
# >>>:clIeNt1
# clet1 ('127.0.0.1', 8080)
# >>>:CLienT1
# client1 ('127.0.0.1', 8080)
# >>>:
# 窗口2 控制台数据(输入与输出)
# >>>:CLient2
# client2 ('127.0.0.1', 8080)
# >>>:
# 窗口1 控制台数据(输入与输出)
# >>>:CLiEnt3
# client3 ('127.0.0.1', 8080)
# >>>:
为什么UDP时重写的handle方法里不用写通信循环
handle 是处理一次连接请求的,handle结束连接就断开了
UDP是不需要保持(双向)连接的,所以每次sendto 都是单个请求(都附带服务器端地址及端口),不能写通信循环(不然就拿着一个sendto 过来的数据循环打印了)
而TCP是基于双向通道通信的,handle结束后连接就断开了(再client.send() 这个连接状态就已经不存在了),所以TCP这边的服务端要写通信循环保持连接来多次通信
python异常处理-异常捕获-抛出异常-断言-自定义异常-UDP通信-socketserver模块应用-3的更多相关文章
- Python进阶----UDP协议使用socket通信,socketserver模块实现并发
Python进阶----UDP协议使用socket通信,socketserver模块实现并发 一丶基于UDP协议的socket 实现UDP协议传输数据 代码如下:
- UDP协议&socketserver模块
UDP协议&socketserver模块 一.UDP协议 1.1 UDP实现简单通信 服务器 ------------------------------------------------- ...
- 【python】-- try except (异常捕获)、断言
try except (异常捕获) 当程序出错了,但是我们又不想让用户看到这个错误,而且我在写程序的时候已经预料到了它可以出现这样的错误,出现这样的错误代表着什么,我们可以提前捕获这些个错误 1.异常 ...
- T-SQL编程中的异常处理-异常捕获(catch)与抛出异常(throw)
本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出,本文简单介绍异常捕获与异 ...
- T-SQL编程中的异常处理-异常捕获(try catch)与抛出异常(throw)
本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出(try catch th ...
- python入门19 异常及异常处理 异常捕获
常见异常举例 """ 一些异常举例:""" '''模块不存在 ModuleNotFoundError: No module named 'd ...
- Python标准异常和异常处理详解
python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 1.异常处理: 本站Python教程会具体介绍. 2.断言(Asserti ...
- try except 异常捕获的方法、断言的使用
except as e中的'e'的作用总结 - 2puT - CSDN博客 Python使用try except处理程序异常的三种常用方法分析 Python3和Python2 异常处理except的不 ...
- Python异常处理与上下文管理器
Python异常处理 异常与错误 错误 可以通过IDE或者解释器给出提示的错误opentxt('a.jpg','r') 语法层面没有问题,但是自己代码的逻辑有问题if age>18: print ...
随机推荐
- python爬虫之快速对js内容进行破解
python爬虫之快速对js内容进行破解 今天介绍下数据被js加密后的破解方法.距离上次发文已经过去半个多月了,我写文章的主要目的是把从其它地方学到的东西做个记录顺便分享给大家,我承认自己是个懒猪.不 ...
- Java Volatile 关键字详解
原文链接:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性 ...
- 源码阅读 - java.util.concurrent (一)
java.util.concurrent这个包大致可以分为五个部分: Aomic数据类型 这部分都被放在java.util.concurrent.atomic这个包里面,实现了原子化操作的数据类型,包 ...
- XTOJ 1267:Highway(树的直径)***
http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1267 题意:给出一棵树,每条树边有权值,现在要修建n-1条边,边的权值为边 ...
- HDU 2896:病毒侵袭(AC自动机)
http://acm.hdu.edu.cn/showproblem.php?pid=2896 题意:中文题意. 思路:AC自动机模板题.主要在于字符有128种,输出还要排序和去重! 注意是“total ...
- 使用Xcode + Python进行IOS运动轨迹模拟
前言 在某些app中,需要根据用户的实时位置来完成某些事件 例如跑步打卡软件(步道乐跑).考勤打卡软件(叮叮).某些基于实时位置的游戏(Pokemon Go.一起来捉妖) 一般解决办法是通过使用安卓模 ...
- Modbus 指令
本节内容: 一.S7-1200 作为Modbus RTU 主站 二.S7-1200 作为Modbus RTU 从站 三.S7-1200 作为Modbus RTU 主站 S7-1200 作为Modbus ...
- EPPLUS 实现excel报表数据及公式填充
年后工作第一天,根据客户要求修善EPPLUS报表. Epplus: Epplus是一个使用Open Office XML(Xlsx)文件格式,能读写Excel 2007/2010文件的开源组件 好处很 ...
- 使用DQL查询数据库
DQL ( Data Query Language) 是数据查询语言,如 Select 语句#### 一.DQL 语法 ```sqlSELECT [ALL | DISTINCT]{* | table. ...
- CentOS 7.3 配置静态ip
镜像:CentOS-7-x86_64-DVD-1511.iso 1.修改.查看虚拟机的网段 1.1.查看虚拟机网段 编辑-> 虚拟机网络编辑器,修改的需要管理员权限 选择NAT模式 点击 NAT ...