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
>>>
复制代码

以上。


目录
相关文章
|
27天前
|
前端开发 JavaScript UED
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
通过在Django项目中集成Channels和WebSocket,我们能够为前后端分离的应用添加实时通信功能,实现诸如在线聊天、实时数据更新等交互式场景。这不仅增强了应用的功能性,也提升了用户体验。随着实时Web应用的日益普及,掌握Django Channels和WebSocket的集成将为开发者开启新的可能性,推动Web应用的发展迈向更高层次的实时性和交互性。
53 1
|
3天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
Python Web框架比较:Django vs Flask vs Pyramid
11 1
|
14天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
Python Web框架比较:Django vs Flask vs Pyramid
16 4
|
15天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第10天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django以功能全面、文档完善著称,适合快速开发;Flask轻量灵活,易于上手;Pyramid介于两者之间,兼顾灵活性和安全性。选择框架时需考虑项目需求和个人偏好。
25 1
|
20天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【10月更文挑战第6天】本文比较了Python中三个最受欢迎的Web框架:Django、Flask和Pyramid。Django功能全面,适合快速开发;Flask灵活轻量,易于上手;Pyramid介于两者之间,兼顾灵活性和可扩展性。文章分析了各框架的优缺点,帮助开发者根据项目需求和个人偏好做出合适的选择。
27 4
|
2月前
|
机器学习/深度学习 人工智能 算法
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
文本分类识别系统。本系统使用Python作为主要开发语言,首先收集了10种中文文本数据集("体育类", "财经类", "房产类", "家居类", "教育类", "科技类", "时尚类", "时政类", "游戏类", "娱乐类"),然后基于TensorFlow搭建CNN卷积神经网络算法模型。通过对数据集进行多轮迭代训练,最后得到一个识别精度较高的模型,并保存为本地的h5格式。然后使用Django开发Web网页端操作界面,实现用户上传一段文本识别其所属的类别。
79 1
【新闻文本分类识别系统】Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+Django网页界面平台
|
26天前
|
存储 Shell 数据库
Python编程--Django入门:用户账户(二)
Python编程--Django入门:用户账户(二)
16 2
|
26天前
|
存储 数据库 Python
Python编程--Django入门:用户账户(一)
Python编程--Django入门:用户账户(一)
16 1
|
26天前
|
存储 大数据 数据处理
Python 中的列表推导式与生成器:特性、用途与区别
Python 中的列表推导式与生成器:特性、用途与区别
14 2
|
27天前
|
存储 C语言 Python
解密 Python 的变量和对象,它们之间有什么区别和联系呢?
解密 Python 的变量和对象,它们之间有什么区别和联系呢?
17 2