Python-schema的使用

2023-10-27

不管我们做什么应用,只要和用户输入打交道,就有一个原则–永远不要相信用户的输入数据。意味着我们要对用户输入进行严格的验证,web开发时一般输入数据都以JSON形式发送到后端API,API要对输入数据做验证。一般我都是加很多判断,各种if,导致代码很丑陋,能不能有一种方式比较优雅的验证用户数据呢?Schema就派上用场了。

安装

pip install schema

Schema

基本类型:满足条件后会返回当前的值,不满足将报错!

from schema import Schema

print Schema(int).validate(10)      # 10
print Schema(int).validate('10')    # schema.SchemaUnexpectedTypeError

list/tuple/set:只需满足list/tuple/set中的其中一个条件后会返回当前的值,不满足将报错!!

from schema import Schema

print Schema([int, float]).validate([1, 2, 3, 3.3])             # [1, 2, 3, 3.3]
print Schema([int, float]).validate([1, 2, 3, 4])               # [1, 2, 3, 4]
print Schema([int, float]).validate(['a', 'b', 'c', 'd'])       # schema.SchemaError

字典:首先,模型字典与数据字典的Key是否完全一样,不一样将报错;而后,那数据字典的value验证模型字典相应的value,如果验证通过才会返回数据,否则将会报错

from schema import Schema

print Schema({"name": str, "age": int}).validate({"name": "laozhang", "age": 18})           # {'age': 18, 'name': 'laozhang'}
print Schema({"name": str, "age": int}).validate({"name": "laozhang"})                      # schema.SchemaMissingKeyError
print Schema({"name": str, "age": int}).validate({"name": 18, "age": 18})                   # schema.SchemaError
print Schema({"name": str, "age": int}).validate({"name": 18, "age": 18, "addr": "广东"})   # schema.SchemaWrongKeyError

有个概念值得注意:Schema传入的字典,我们通常称之为模型字典,validate传入的字典,我们通常称之为数据字典

可调用的对象:满足可调用的对象的条件后会返回当前的值,不满足将报错!

from schema import Schema

print Schema(lambda x: 1 < x < 8).validate(5)       # 5
print Schema(lambda x: 1 < x < 8).validate(8)       # schema.SchemaError

Use

Use在验证的时候,会自动帮你转换它的值

from schema import Schema, Use

print Schema(Use(int)).validate(10)                 # 10-->int类型
print Schema(Use(int)).validate('10')               # 10-->int类型
print Schema(Use(int)).validate('xiaoming')         # schema.SchemaError

Const

我们知道Use在验证的时候,会自动帮你转换它的值。Const可以保持原始数据不变:

from schema import Schema, Use, Const

print Schema(Const(Use(int))).validate('10')        # 10-->str类型

And

And对是否满足多个条件进行验证

from schema import Schema, And

print Schema(And(int, lambda x: x < x < 8)).validate(5)             # 5
print Schema(And(int, lambda x: x < x < 8)).validate(8)             # schema.SchemaError
print Schema(And(int, lambda x: x < x < 8)).validate('5')           # schema.SchemaError

Or

Or对是否满足其中一个条件进行验证

from schema import Schema, Or, Use

print Schema(Or(lambda x: 1 < x < 8, Use(int))).validate(5)                 # 5-->int类型
print Schema(Or(lambda x: 1 < x < 8, Use(int))).validate(8)                 # 8-->int类型
print Schema(Or(lambda x: 1 < x < 8, Use(int))).validate('8')               # 8-->int类型
print Schema(Or(lambda x: 1 < x < 8, Use(int))).validate('xiaoming')        # schema.SchemaError

Optional

Schema传入字典进行验证很好用,可是常常因为传入的字典与模型字典key不匹配,从而导致报错,此时我们可以使用Optional进行可选验证字典:

from schema import Schema, Optional

print Schema({"name": str, Optional("age"): int}).validate({"name": "laozhang"})                                # {'name': 'laozhang'}
print Schema({"name": str, Optional("age"): int}).validate({"name": "laozhang", "age": 18})                     # {'age': 18, 'name': 'laozhang'}
print Schema({"name": str, Optional("age"): int}).validate({"name": 18, "age": 18})                             # schema.SchemaError
print Schema({"name": str, Optional("age"): int}).validate({"name": "laozhang", "age": 18, "addr": "广东"})     # schema.SchemaWrongKeyError

我们还可以在Optional中设置一个默认值,如下:

print Schema({"name": str, Optional("age", default=18): int}).validate({"name": "laozhang"})                    # {'age': 18, 'name': 'laozhang'}

上面这种方式只是用于数据字典的key比模型字典的key少的情况,如果数据字典的key比模型字典的多,那么又该如何进行忽略验证呢?我们可以使用ignore_extra_keys参数,并将其设置为True,如下:

from schema import Schema

print Schema({"name": str, "age": int}, ignore_extra_keys=True).validate({"name": "laozhang", "age": 18, "addr": "广东"})       # {'age': 18, 'name': 'laozhang'}

Forbidden

Forbidden可以将某个key禁止:

from schema import Schema, Forbidden

print Schema({Forbidden('name'): str, 'age': int}).validate({"age": 15})                            # {"age": 15}
print Schema({Forbidden('name'): str, 'age': int}).validate({"name": "laozhang", "age": 15})        # schema.SchemaForbiddenKeyError
print Schema({Forbidden('name'): str, 'age': int}).validate({"name": 10, "age": 15})                # schema.SchemaWrongKeyError

值得注意的是,与禁用秘钥配对的值将决定了它是否会被拒绝:

from schema import Schema, Forbidden

print Schema({Forbidden('name'): int, 'name': str}).validate({'name': 'laozhang'})                  # {'name': 'laozhang'}
print Schema({Forbidden('name'): str, 'name': str}).validate({'name': 'laozhang'})                  # schema.SchemaForbiddenKeyError

另外,Forbidden的优先级要比Optional要高:

from schema import Schema, Forbidden, Optional

print Schema({Forbidden('name'): str, Optional('name'): str}).validate({"name": "laozhang"})        # schema.SchemaForbiddenKeyError

Regex

Regex可以根据正则表达式进行匹配验证

import re
from schema import Regex

print Regex('^foo').validate('football')        # football
print Regex('^foo').validate('basketball')      # schema.SchemaError

# flags=re.I忽略大小写
print Regex('[A-Z]+', flags=re.I).validate('football')      # football

当然,Regex同样也可以配合Schema一起使用:

from schema import Schema, Regex

print Schema(Regex('^foo')).validate('football')            # football

自定义错误

SchemaAndOrUse等类都有一个参数error,可以自定义错误信息:

from schema import Schema

print Schema(int, error='只能是整数类型').validate('abc')      # schema.SchemaUnexpectedTypeError: 只能是整数类型
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python-schema的使用 的相关文章

  • Python BigQuery 存储。并行读取多个流

    我有以下玩具代码 import pandas as pd from google cloud import bigquery storage v1beta1 import os import google auth os environ G
  • 下载 PyQt6 的 Qt Designer 并使用 pyuic6 将 .ui 文件转换为 .py 文件

    如何下载 PyQt6 的 QtDesigner 如果没有适用于 PyQt6 的 QtDesigner 我也可以使用 PyQt5 的 QtDesigner 但是如何将此 ui 文件转换为使用 PyQt6 库而不是 PyQt5 的 py 文件
  • Python PAM 模块的安全问题?

    我有兴趣编写一个 PAM 模块 该模块将利用流行的 Unix 登录身份验证机制 我过去的大部分编程经验都是使用 Python 进行的 并且我正在交互的系统已经有一个 Python API 我用谷歌搜索发现pam python http pa
  • Pycharm Python 控制台不打印输出

    我有一个从 Pycharm python 控制台调用的函数 但没有显示输出 In 2 def problem1 6 for i in range 1 101 2 print i end In 3 problem1 6 In 4 另一方面 像
  • 如何收集列表、字典等中重复计算的结果(或制作修改每个元素的列表的副本)?

    There are a great many existing Q A on Stack Overflow on this general theme but they are all either poor quality typical
  • DreamPie 不适用于 Python 3.2

    我最喜欢的 Python shell 是DreamPie http dreampie sourceforge net 我想将它与 Python 3 2 一起使用 我使用了 添加解释器 DreamPie 应用程序并添加了 Python 3 2
  • 如何在 Sublime Text 2 的 OSX 终端中显示构建结果

    我刚刚从 TextMate 切换到 Sublime Text 2 我非常喜欢它 让我困扰的一件事是默认的构建结果显示在 ST2 的底部 我的程序产生一些很长的结果 显示它的理想方式 如在 TM2 中 是并排查看它们 如何在 Mac 操作系统
  • 打破嵌套循环[重复]

    这个问题在这里已经有答案了 有没有比抛出异常更简单的方法来打破嵌套循环 在Perl https en wikipedia org wiki Perl 您可以为每个循环指定标签 并且至少继续一个外循环 for x in range 10 fo
  • Spark的distinct()函数是否仅对每个分区中的不同元组进行洗牌

    据我了解 distinct 哈希分区 RDD 来识别唯一键 但它是否针对仅移动每个分区的不同元组进行了优化 想象一个具有以下分区的 RDD 1 2 2 1 4 2 2 1 3 3 5 4 5 5 5 在此 RDD 上的不同键上 所有重复键
  • Python tcl 未正确安装

    我刚刚为 python 安装了graphics py 但是当我尝试运行以下代码时 from graphics import def main win GraphWin My Circle 100 100 c Circle Point 50
  • 从列表中的数据框列中搜索部分字符串匹配 - Pandas - Python

    我有一个清单 things A1 B2 C3 我有一个 pandas 数据框 其中有一列包含用分号分隔的值 某些行将包含与上面列表中的一项的匹配 它不会是完美的匹配 因为它在其中包含字符串的其他部分 该列 例如 该列中的一行可能有 哇 这里
  • Python 中的二进制缓冲区

    在Python中你可以使用StringIO https docs python org library struct html用于字符数据的类似文件的缓冲区 内存映射文件 https docs python org library mmap
  • Python:字符串不会转换为浮点数[重复]

    这个问题在这里已经有答案了 我几个小时前写了这个程序 while True print What would you like me to double line raw input gt if line done break else f
  • 通过数据框与函数进行交互

    如果我有这样的日期框架 氮 EG 00 04 NEG 04 08 NEG 08 12 NEG 12 16 NEG 16 20 NEG 20 24 datum von 2017 10 12 21 69 15 36 0 87 1 42 0 76
  • Python 3 中“map”类型的对象没有 len()

    我在使用 Python 3 时遇到问题 我得到了 Python 2 7 代码 目前我正在尝试更新它 我收到错误 类型错误 map 类型的对象没有 len 在这部分 str len seed candidates 在我像这样初始化它之前 se
  • VSCode:调试配置中的 Python 路径无效

    对 Python 和 VSCode 以及 stackoverflow 非常陌生 直到最近 我已经使用了大约 3 个月 一切都很好 当尝试在调试器中运行任何基本的 Python 程序时 弹出窗口The Python path in your
  • glpk.LPX 向后兼容性?

    较新版本的glpk没有LPXapi 旧包需要它 我如何使用旧包 例如COBRA http opencobra sourceforge net openCOBRA Welcome html 与较新版本的glpk 注意COBRA适用于 MATL
  • 在 Python 类中动态定义实例字段

    我是 Python 新手 主要从事 Java 编程 我目前正在思考Python中的类是如何实例化的 我明白那个 init 就像Java中的构造函数 然而 有时 python 类没有 init 方法 在这种情况下我假设有一个默认构造函数 就像
  • 改变字典的哈希函数

    按照此question https stackoverflow com questions 37100390 towards understanding dictionaries 我们知道两个不同的字典 dict 1 and dict 2例
  • Pandas 与 Numpy 数据帧

    看这几行代码 df2 df copy df2 1 df 1 df 1 values 1 df2 ix 0 0 我们的教练说我们需要使用 values属性来访问底层的 numpy 数组 否则我们的代码将无法工作 我知道 pandas Data

随机推荐

  • 夜莺(Flashcat)V6监控(五):夜莺监控k8s组件(下)---使用kube-state-metrics监控K8s对象

    目录 一 前言 二 categraf作为Daemonset的方式去运行监控k8s组件 1 1 24版本以下的k8s集群部署方法 创建autu yaml绑定权限 Daemonset部署categraf采集监控kubelet kube prox
  • 在jsp页面获取url请求参数

    JSP页面 When using the JSTL s expression language the request parameters are made available in the implicit object param T
  • css flex布局 —— 项目属性 flex-grow

    flex grow 属性定义项目的放大比例 解决的问题是 在空间有多余时把多余空间分配给各个子元素 flex grow 的值默认为 0 也就是说 如果存在剩余空间 也不放大 flex grow 取值为非负数 如果取值为负数那么和0的取值效果
  • mybatis拦截器

    最近在用mybatis做项目 需要用到mybatis的拦截器功能 就顺便把mybatis的拦截器源码大致的看了一遍 为了温故而知新 在此就按照自己的理解由浅入深的理解一下它的设计 和大家分享一下 不足和谬误之处欢迎交流 直接入正题 首先 先
  • 踩坑将一个AndroidStudio项目变成一个module引入到自己的项目中

    最近工作中遇到了需要将一个完整的androidstudio项目移植到自己项目中去 因为考虑到自己已经有的项目和需要引入的项目资源都很庞大 为了方便代码管理 决定将需要引入的项目作为一个module导入到自己现有项目中来 操作步骤 1 在主项
  • Cookie 与 Session 的作用及区别

    Cookie Cookie 其实就是客户端储存的 什么是客户端 就是浏览器存储 能看的见的 在浏览器设置 历史纪录中能看见 能手动清除Cookie 所以它一般都会被用在不重要的地方 因为它很容易被发现 cookie以明文储存信息 而且储存量
  • unity中lightProbe的使用

    之前曾经介绍过Unity3D的LightMapping烘焙的用法 单独使用的LightMapping效果很好 但由于只是把光影烘焙到贴图上面 所以并不会对周围的动态物体产生真正的光照效果 这次来介绍一下LightProbe 这是对Light
  • 服务器小程序空间,服务器空间-小程序-建站-企业邮箱

    Your twitter username username wange1228 Prefix some text you want displayed before your latest tweet HTML is OK but be
  • 华为OD机试 - 单词倒序(Java)

    题目描述 输入单行英文句子 里面包含英文字母 空格以及 三种标点符号 请将句子内每个单词进行倒序 并输出倒序后的语句 输入描述 输入字符串S S的长度 1 N 100 输出描述 输出倒序后的字符串 备注 标点符号左右的空格 0 单词间空格
  • C语言 -- 动态数组&链表

    目录 动态数组 动态数组的实现 用户test 链表 目的 链表的结构体 链表的实现 初始化链表 插入节点 遍历链表 删除节点 清空链表 销毁链表 用户回调函数 给用户提供接口获取链表长度 用户test 动态数组 将数组开辟到堆区 实现动态扩
  • ubuntu 16.04安装 jdk 1.9

    1 命令行输入javac 提示java尚未安装 选择提示中的包进行安装 2 执行 sudo apt install 安装jdk的版本号 根据提示确认安装 3 配置jdk路径 执行 sudo gedit etc profile 输入密码打开文
  • c++ STL vector知识点

    c 知识点 vector基本概念及定义 vector函数的构造 vector函数实现 vector基本概念及定义 头文件 include
  • VTK入门001——HelloVTK

    include VTKPlatform h vtkConeSource 是 VTK 库中的一个类 用于生成一个圆锥体的几何形状 include
  • 网站数据分析报告怎么写?

    网站数据分析报告怎么写 1 目标 Objective 是前提 网站分析报告的起点不是从现象开始的 而是从网站的目标 objective 开始的 我相信大多数网站的目标不应该超过1个 那些各种目标都应该归结为一个最终的最根本的目标 如果你的老
  • CTF show 萌新web-1

    首先看题目 代码整体逻辑是先通过GET请求传递参数id 如果id大于999 报错 如果小于999 则输出当前的执行的sql语句 如果根据id参数能在数据库中查到值 row 则将其打印出来 而flag则是id为1000的 row中的内容 这道
  • excel表格(.csv)保存到数据库--QT数据库

    刚学QT的菜鸟 无聊的时候总会找一点事情做 言归正传 将excel表格保存到数据库 是比较简单的 我的想法简单粗暴 从路径中获取文件 通过按键控制加载 将大象放进冰箱需要是三步 这个同样 1 获取路径 2 读取Excel文件 3 将其保存到
  • Domain-Specific Languages 23

    Domain Specific Languages Whenever you listen to a discussion by experts in any domain be it chess players kindergarten
  • 红日靶场(五)

    红日5 一 环境搭建 此次靶场虚拟机共用两个 一个外网一个内网 用来练习红队相关内容和方向 主要包括常规信息收集 Web攻防 代码审计 漏洞利用 内网渗透以及域渗透等相关内容学习 1 环境拓扑图 2 靶机下载地址 漏洞详情 3 我们设置VM
  • elasticsearch 集群配置

    主节点配置 集群名称 cluster name demo 节点名称 每个节点的名称不能重复 node name es node 1 ip 地址 每个节点的地址不能重复 network host 172 16 10 1 是不是有资格主节点 n
  • Python-schema的使用

    不管我们做什么应用 只要和用户输入打交道 就有一个原则 永远不要相信用户的输入数据 意味着我们要对用户输入进行严格的验证 web开发时一般输入数据都以JSON形式发送到后端API API要对输入数据做验证 一般我都是加很多判断 各种if 导