Python 中 \x00 和空字符串的区别,以及在 Django 中的坑

简介: 事情是这样的,我有一个守护进程,不停地从 RabbitMQ 消费数据,然后保存到 MySQL。操作数据库使用的是 Django 的 ORM 语法。

事情是这样的,我有一个守护进程,不停地从 RabbitMQ 消费数据,然后保存到 MySQL。操作数据库使用的是 Django 的 ORM 语法。


最近一段时间,频繁发生一个问题,就是有一类数据,守护进程从后台使用 create 方法,直接入库完全没问题。但是,在页面上,通过表单来修改这条数据,无论如何都无法保存成功,报错信息提示某一个字段不能为空。但是这个字段明明是有值的,很让人费解。


仔细分析了代码之后,感觉可能发生问题的只有这一句:


serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
复制代码


因为打印 serializer 是有值的,所以肯定是 is_valid 做表单验证时给过滤掉了。但是为什么会过滤就需要更深一步去探索了。

通过单步调试,走到函数的调用关系中,发现了问题的关键所在。


```python
# django/forms/fields.py
class CharField(Field):
    def __init__(self, *, max_length=None, min_length=None, strip=True, empty_value='', **kwargs):
        self.max_length = max_length
        self.min_length = min_length
        self.strip = strip
        self.empty_value = empty_value
        super().__init__(**kwargs)
        if min_length is not None:
            self.validators.append(validators.MinLengthValidator(int(min_length)))
        if max_length is not None:
            self.validators.append(validators.MaxLengthValidator(int(max_length)))
        self.validators.append(validators.ProhibitNullCharactersValidator())
        ...
```
复制代码


这段代码只截取了一部分,是对 Model CharField 字段的一些定义,比如最小长度,最大长度等等。除了这些,最后还有一句验证,其中调用了下面这个类:


# django/core/validators.py
@deconstructible
class ProhibitNullCharactersValidator:
    """Validate that the string doesn't contain the null character."""
    message = _('Null characters are not allowed.')
    code = 'null_characters_not_allowed'
    def __init__(self, message=None, code=None):
        if message is not None:
            self.message = message
        if code is not None:
            self.code = code
    def __call__(self, value):
        if '\x00' in str(value):
            raise ValidationError(self.message, code=self.code)
    def __eq__(self, other):
        return (
            isinstance(other, self.__class__) and
            self.message == other.message and
            self.code == other.code
        )
复制代码


而在这个类中,有一个 __call__  方法,如果有 \x00 在需要保存的字段值里,就会抛异常。不知道源码里为什么会有这样的判断。


再回过头来看提示我为空的那个字段的值,其中的确有不可见字符 \x00


到这里,这个问题也就明确了,那怎么解决呢?其实很简单,在后台保存数据时,直接将 \x00 替换掉成空就可以了。


问题是解决了,但是 \x00 和空有什么区别呢?这就又涉及到 Python 的编码问题了。虽然两者都是空,但在很多方面都不相同,下面用一段简单的代码来表现一下:


>>> a = '\x00'
>>> b = ''
>>>
>>> print(a)
>>> print(b)
>>> a == b
False
>>>
>>> len(a)
1
>>> len(b)
0
>>> print('hello\x00world')
helloworld
>>> a = 'hello\x00world'
>>> if '\x00' in a:
...     print('111')
...
111
>>>
复制代码

以上。


目录
相关文章
|
25天前
|
NoSQL Unix 网络安全
【Azure Cache for Redis】Python Django-Redis连接Azure Redis服务遇上(104, 'Connection reset by peer')
【Azure Cache for Redis】Python Django-Redis连接Azure Redis服务遇上(104, 'Connection reset by peer')
【Azure Cache for Redis】Python Django-Redis连接Azure Redis服务遇上(104, 'Connection reset by peer')
|
11天前
|
前端开发 搜索推荐 算法
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
中草药管理与推荐系统。本系统使用Python作为主要开发语言,前端使用HTML,CSS,BootStrap等技术和框架搭建前端界面,后端使用Django框架处理应用请求,使用Ajax等技术实现前后端的数据通信。实现了一个综合性的中草药管理与推荐平台。具体功能如下: - 系统分为普通用户和管理员两个角色 - 普通用户可以登录,注册、查看物品信息、收藏物品、发布评论、编辑个人信息、柱状图饼状图可视化物品信息、并依据用户注册时选择的标签进行推荐 和 根据用户对物品的评分 使用协同过滤推荐算法进行推荐 - 管理员可以在后台对用户和物品信息进行管理编辑
47 12
中草药管理与推荐系统Python+Django网页界面+推荐算法+计算机课设系统+网站开发
|
2天前
|
Python
全网最适合入门的面向对象编程教程:Python函数方法与接口-函数与方法的区别和lamda匿名函数
【9月更文挑战第15天】在 Python 中,函数与方法有所区别:函数是独立的代码块,可通过函数名直接调用,不依赖特定类或对象;方法则是与类或对象关联的函数,通常在类内部定义并通过对象调用。Lambda 函数是一种简洁的匿名函数定义方式,常用于简单的操作或作为其他函数的参数。根据需求,可选择使用函数、方法或 lambda 函数来实现代码逻辑。
|
3天前
|
机器学习/深度学习 人工智能 安全
python和Java的区别以及特性
Python:适合快速开发、易于维护、学习成本低、灵活高效。如果你需要快速上手,写脚本、数据处理、做点机器学习,Python就是你的首选。 Java:适合大型项目、企业级应用,性能要求较高的场景。它类型安全、跨平台能力强,而且有丰富的生态,适合更复杂和规模化的开发。
14 3
|
21天前
|
存储 测试技术 Python
Python 数组和列表有什么区别?
【8月更文挑战第29天】
25 4
|
1月前
|
数据采集 自然语言处理 监控
【优秀python毕设案例】基于python django的新媒体网络舆情数据爬取与分析
本文介绍了一个基于Python Django框架开发的新媒体网络舆情数据爬取与分析系统,该系统利用Scrapy框架抓取微博热搜数据,通过SnowNLP进行情感分析,jieba库进行中文分词处理,并以图表和词云图等形式进行数据可视化展示,以实现对微博热点话题的舆情监控和分析。
【优秀python毕设案例】基于python django的新媒体网络舆情数据爬取与分析
|
21天前
|
C++ Python
python类方法中使用:修饰符@staticmethod和@classmethod的作用与区别,还有装饰器@property的使用
python类方法中使用:修饰符@staticmethod和@classmethod的作用与区别,还有装饰器@property的使用
12 1
|
22天前
|
Python
python中set和frozenset方法和区别
python中set和frozenset方法和区别
|
22天前
|
前端开发 JavaScript 数据库
python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器
python Django教程 之模板渲染、循环、条件判断、常用的标签、过滤器
|
25天前
|
监控 安全 中间件
Python Django 后端架构开发: 中间件架构设计
Python Django 后端架构开发: 中间件架构设计
21 1