异常捕获

异常:程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表现出来

影响:整个程序无法再正常运行

异常的结构

异常的类型

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之间的区别

  1. UDP 允许发空数据,不会有影响
  2. UDP 直接启动客户端未启动服务端不会报错
  3. UDP 不会有粘包问题(自带报头)
  4. 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的更多相关文章

  1. Python进阶----UDP协议使用socket通信,socketserver模块实现并发

    Python进阶----UDP协议使用socket通信,socketserver模块实现并发 一丶基于UDP协议的socket 实现UDP协议传输数据 代码如下:

  2. UDP协议&socketserver模块

    UDP协议&socketserver模块 一.UDP协议 1.1 UDP实现简单通信 服务器 ------------------------------------------------- ...

  3. 【python】-- try except (异常捕获)、断言

    try except (异常捕获) 当程序出错了,但是我们又不想让用户看到这个错误,而且我在写程序的时候已经预料到了它可以出现这样的错误,出现这样的错误代表着什么,我们可以提前捕获这些个错误 1.异常 ...

  4. T-SQL编程中的异常处理-异常捕获(catch)与抛出异常(throw)

    本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出,本文简单介绍异常捕获与异 ...

  5. T-SQL编程中的异常处理-异常捕获(try catch)与抛出异常(throw)

    本文出处: http://www.cnblogs.com/wy123/p/6743515.html T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出(try catch th ...

  6. python入门19 异常及异常处理 异常捕获

    常见异常举例 """ 一些异常举例:""" '''模块不存在 ModuleNotFoundError: No module named 'd ...

  7. Python标准异常和异常处理详解

    python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 1.异常处理: 本站Python教程会具体介绍. 2.断言(Asserti ...

  8. try except 异常捕获的方法、断言的使用

    except as e中的'e'的作用总结 - 2puT - CSDN博客 Python使用try except处理程序异常的三种常用方法分析 Python3和Python2 异常处理except的不 ...

  9. Python异常处理与上下文管理器

    Python异常处理 异常与错误 错误 可以通过IDE或者解释器给出提示的错误opentxt('a.jpg','r') 语法层面没有问题,但是自己代码的逻辑有问题if age>18: print ...

随机推荐

  1. CDH 5.15.2 离线安装

    一.前置准备 1. 基础信息 1.1 机器 机器名 服务 hadoop1 主节点 hadoop2 data.task hadoop3 data.task 1.2 服务版本 服务 版本 cdh 5.15 ...

  2. Oracle Goldengate是如何保证数据有序和确保数据不丢失的?

    工作中一直在用Oracle 的中间件Oracle GondenGate 是如何保证消息的有序和不丢失呢? Oracle GoldenGate逻辑架构 首先,先看一下Oracle GoldenGate ...

  3. 《An Attentive Survey of Attention Models》阅读笔记

    本文是对文献 <An Attentive Survey of Attention Models> 的总结,详细内容请参照原文. 引言 注意力模型现在已经成为神经网络中的一个重要概念,并已经 ...

  4. J2EE:Servlet上传文件到服务器,并相应显示

    Servlet 可以与HTML一起使用来允许用户上传文件到服务器 编辑上传文件的页面upload.html 注意事项:上传方式使用POST不能使用GET(GET不能上传文件) 表单 enctype 属 ...

  5. 20190101.DDD笔记

    建立领域模型步骤 根据提供的信息完善主要业务场景和业务流程: 根据业务流程识别领域事件并按照时序排列: 针对领域事件进行命令识别: 针对领域事件和命令进行聚合和子域的初步识别: 在识别的subdoma ...

  6. UVA1327 && POJ1904 King's Quest(tarjan+巧妙建图+强连通分量+缩点)

    UVA1327 King's Quest POJ1904 King's Quest 题意: 有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚.现有一个匹配表,将每个王子都与一个自己 ...

  7. Excel催化剂开源第42波-与金融大数据TuShare对接实现零门槛零代码获取数据

    在金融大数据功能中,使用了TuShare的数据接口,其所有接口都采用WebAPI的方式提供,本来还在纠结着应该搬那些数据接口给用户使用,后来发现,所有数据接口都有其通用性,结合Excel灵活友好的输入 ...

  8. Excel催化剂开源第11波-动态数组函数技术开源及要点讲述

    在Excel催化剂中,大量的自定义函数使用了动态数组函数效果,虽然不是原生的Excel365版效果(听说Excel2019版取消了支持动态数组函数,还没求证到位,Excel365是可以用,但也仅限于部 ...

  9. u盘制作启动盘步骤以及安装win10步骤

    1.下载制作工具:微PE工具箱V2.0 http://www.wepe.com.cn/download.html 2.默认制作启动盘 3.下载win10镜像 ed2k://|file|cn_windo ...

  10. APP爬虫(2)把小姐姐的图片down下来

    APP爬虫(1)想学新语言,又没有动力,怎么办? 书接上文.使用appium在帖子列表界面模拟上划动作,捕捉不到列表的规律.上划结束后,列表只能获取到屏幕呈现的部分,而且下标还是从0开始的. 根据酸奶 ...