oxml中创建CT_Document类
概述
本文基于python-docx源码,详细记录CT_Document类创建的过程,以此来加深对Python中元类、以及CT_Document元素类的认识。
元类简介
元类(MetaClass)是Python中的高级特性。元类是什么呢?Python是面向对象编程语言,在Python中一切事物都是对象。如实例是类对象的实例化结果,而类则是元类实例化的结果。简而言之,元类是创建“类”的“类”——通过元类的__new__与__init__特殊方法管理类的创建过程。其中type对象是Python中内置的元类对象。
那为什么需要元类呢?元类有很强大的功能,本文仅从“为新创建的类自动创建方法”为例进行记录。
元类的定义与使用
通过继承type对象来创建自己的元类:
class MyMetaClass(type):def __new__(cls, name, bases, attrs):print(f"Creating new class: {name}")return super().__new__(cls, name, bases, attrs)
name
参数是新创建类的类名称,bases
参数是新创建类的父类元祖,attrs
是新创建类的属性字典。自定义完元类后,可以在类定义中通过“metaclass”关键字参数明使用自定义的元类,如果不指定,默认值为type对象:
class MyNewClass(metaclass=MyMetaClass):pass
当python解释器创建“基于自定义元类定义的新建类”时,就会调用自定义元类的__new__与__init__特殊方法,从而管理类的创建过程。
新建CT_Document元素类
CT_Document源码定义
CT_Document源码定义于“docx.oxml.document”模块,表示一个XML文档元素类(类别lxml.etree.ElementBase)。
class CT_Document(BaseOxmlElement):"""``<w:document>`` element, the root element of a document.xml file."""body: CT_Body = ZeroOrOne("w:body") # pyright: ignore[reportAssignmentType]@propertydef sectPr_lst(self) -> List[CT_SectPr]:"""All `w:sectPr` elements directly accessible from document element.Note this does not include a `sectPr` child in a paragraphs wrapped inrevision marks or other intervening layer, perhaps `w:sdt` or customXmlelements.`w:sectPr` elements appear in document order. The last one is always`w:body/w:sectPr`, all preceding are `w:p/w:pPr/w:sectPr`."""xpath = "./w:body/w:p/w:pPr/w:sectPr | ./w:body/w:sectPr"return self.xpath(xpath)
- CT_Document类定义两个属性,其中
body
属性值是“CT_Body”类型,其取值为“ZeroOrOne”类型。注意限定性属性名为“w:body”。 - 除了
sectpr_lst
与body
属性被显示定义外,其它属性继承于BaseOxmlElement类。
接下来本文将详细记录,python中的元类功能,如何自动为CT_Document添加许多方法。
BaseOxmlElement 基层类
BaseOxmlElement基础元素类是一种类似于lxml.etree.ElementBase的类对象,只是其遵循的是Office Open XML标准。首先看docx.oxml.xmlchemy源码定义:
# -- lxml typing isn't quite right here, just ignore this error on _Element --
class BaseOxmlElement(etree.ElementBase, metaclass=MetaOxmlElement):"""Effective base class for all custom element classes.Adds standardized behavior to all classes in one place."""def __repr__(self):return "<%s '<%s>' at 0x%0x>" % (self.__class__.__name__,self._nsptag,id(self),)
BaseOxmlElement类的定义比较简单,关于XML的元素类功能大部分继承自etree.ElementBase——作为BaseOxmlElement的父类,而其“类型”是MetaOxmlElement元类。
MetaOxmlElement元类
MetaOxmlElement元类定义于docx.oxml.xmlchemy模块:
class MetaOxmlElement(type):"""Metaclass for BaseOxmlElement."""def __init__(cls, clsname: str, bases: Tuple[type, ...], namespace: Dict[str, Any]):dispatchable = (OneAndOnlyOne,OneOrMore,OptionalAttribute,RequiredAttribute,ZeroOrMore,ZeroOrOne,ZeroOrOneChoice,)for key, value in namespace.items():if isinstance(value, dispatchable):value.populate_class_members(cls, key)
MetaOxmlElement元类依然继承了type的__new__方法,但覆盖了__init__方法。__init__方法的逻辑也比较简单,如果namespace
属性字典中的值是源码中指定的dispatchable
类型,则调用对应类的populate_class_members方法。
_BaseChildElement类
_BaseChildElement类定义于docx.oxml.xmlchemy模块,为什么要在这里介绍此类?因为元类MetaOxmlElement的__init__方法中的dispatchable
元组中,除了OptionalAttribute与RequiredAttribute外——但功能|角色有很大的相似性,其它类都是继承该基础类;并且后续许多自动为新创建的类添加方法,也与此类有关,因此在此处加以介绍。
class _BaseChildElement:"""Base class for the child-element classes.The child-element sub-classes correspond to varying cardinalities, such as ZeroOrOneand ZeroOrMore."""def __init__(self, nsptagname: str, successors: Tuple[str, ...] = ()):super(_BaseChildElement, self).__init__()self._nsptagname = nsptagnameself._successors = successorsdef populate_class_members(self, element_cls: MetaOxmlElement, prop_name: str) -> None:"""Baseline behavior for adding the appropriate methods to `element_cls`."""self._element_cls = element_clsself._prop_name = prop_name
- _BaseChildElement是一个典型的类定义,其父类是Python中的object对象。
- 初始化该类需要传入元素“命名空间前缀标签名称”与successors前置元素对象列表——比如一个<w:r>元素,可能需要传入段落格式<w:pPr>等前置元素对象。
- _BaseChildElement基础子类的populate_class_members方法的逻辑比较简单,将传入的参数值存储到实例属性中。
- 注意:prop_name一般为新创建类的属性名,而element_cls一般为新建类**。**_BaseChildElement或者其子类一般是作为新建类(基于MetaOxmlElement元类)的属性。将会结合后面的实例进行说明。
CT_Document创建细节
step1.Python解释器收集必要信息
本文基于Pycharm & Debug模式,调试下列脚本——仅包含一行代码:
from docx.oxml.document import CT_Document
调试模式下,跳转到源码中的class CT_Document(BaseOxmlElement):
行:
-
由于CT_Document的继承自BaseOxmlElement,而BaseOxmlElement是基于MetaOxmlElement元类创建的,因此CT_Document的默认metaclass为MetaOxmlElement元类。创建CT_Document时,会自动调用MetaOxmlElement元类的__init__方法。
-
namespace
属性字典中body属性值,存储的是一个ZeroOrOne实例对象。
step2. 执行MetaOxmlElement.__init__
在执行MetaOxmlElement.__init__的逻辑中,当key=body
& value=ZeroOrOne()
时,会执行ZeroOrOne.populate_class_members(cls, key)
,此时的cls
为“CT_Document”类。
此时许多私有方法显示状态异常,是因为“method_name”需要根据“prop_name”动态生成,而“prop_name”还未被ZeroOrOne实例引用。当执行完_BaseChildElement.populate_class_members
后,异常状态就会消失。
step3. 执行ZeroOrOne.populate_class_members
_BaseChildElement实例方法 | 被封装的函数 | 自动为新建类添加的方法名模版 | 示例值 | 新建方法功能 | 说明 |
---|---|---|---|---|---|
_add_getter | get_child_element | property_name | body | 读取body子节点,如果不存在,则返回None | body作为可读特性,会覆盖CT_Document源码定义中的类属性值 |
_add_creator | new_child_element | “_new_%s” % property_name | _new_body | 根据限定性标签名称,创建一个空的子节点 | 私有方法/辅助方法;创建空白子节点的能力继承lxml |
_add_inserter | _insert_child | “_insert_%s” % property_name | _insert_body | 将子节点插入到父节点中的指定为止 | 私有方法/辅助方法;插入子元素节点的能力继承自lxml |
_add_adder | _add_child | “_add_%s” % property_name | _add_body | 新建子节点,并将子节点插入到父节点中的指定为止 | 私有方法/辅助方法;可以看作是_add_creator & _add_inserter 功能的集成 |
_add_get_or_adder | get_or_add_child | “get_or_add_%s” % property_name | get_or_add_body | 获取或者新建目标子节点 | 非私有方法;可以看作是_add_getter & _add_adder 功能的集成 |
_add_remover | _remove_child | “_remove_%s” % property_name | _remove_body | 从父节点中删除目标子节点 | 私有方法/辅助方法;删除子节点的能力继承自lxml |
"_add_%s"系列的实例方法均定义于 _BaseChildElement,被封装的函数、及新增方法模版名称也均定义于 _BaseChildElement。oxml子库中为新创建的元素类自动添加对应的方法的逻辑,就在"_add_%s"系列的方法中实现。
执行_BaseChildElement.populate_class_members
创建对新建类、属性名的引用。即第一行将“CT_Document”实例对象与“body”特性名称存储到ZeroOrOne实例对象属性中。第2-7行为CT_Documet类自动添加方法。
self._add_getter
_add_getter方法定义于_BaseChildElement类中,其源码如下:
def _add_getter(self):"""Add a read-only ``{prop_name}`` property to the element class for this childelement."""property_ = property(self._getter, None, None)# -- assign unconditionally to overwrite element name definition --setattr(self._element_cls, self._prop_name, property_)
其中self.getter
实例方法定义于_BaseChildElement类中,其源码如下:
@property
def _getter(self):"""Return a function object suitable for the "get" side of the propertydescriptor.This default getter returns the child element with matching tag name or |None|if not present."""def get_child_element(obj: BaseOxmlElement):return obj.find(qn(self._nsptagname))get_child_element.__doc__ = ("``<%s>`` child element or |None| if not present." % self._nsptagname)return get_child_element
self.getter
实例方法即根据限定性标签名称“w:body”在CT_Document元素节点内查找子节点对象。执行setattr(self._element_cls, self._prop_name, property_)
之前,CT_Document的body数值存储的是ZeroOrOne实例对象——定义于源码,执行完成之后,CT_Document的body类属性就对应一个body特征了。
self._add_creator
self._add_creator方法的功能是为新创建的类——根据上下文就是CT_Document,添加一个方法——根据限定性标签名称(w:body),为新创建的类,创建一个空的新子节点元素对象。
def _add_creator(self):"""Add a ``_new_{prop_name}()`` method to the element class that creates a new,empty element of the correct type, having no attributes."""creator = self._creatorcreator.__doc__ = ('Return a "loose", newly created ``<%s>`` element having no attri'"butes, text, or children." % self._nsptagname)self._add_to_class(self._new_method_name, creator)@propertydef _creator(self) -> Callable[[BaseOxmlElement], BaseOxmlElement]:"""Callable that creates an empty element of the right type, with no attrs."""from docx.oxml.parser import OxmlElementdef new_child_element(obj: BaseOxmlElement):return OxmlElement(self._nsptagname)return new_child_element
注意“self._add_to_class”实例方法定义于_BaseChildElement类中,其功能是为新创建的类添加新方法:
def _add_to_class(self, name: str, method: Callable[..., Any]):"""Add `method` to the target class as `name`, unless `name` is already definedon the class."""if hasattr(self._element_cls, name):returnsetattr(self._element_cls, name, method)
结合上下文,self._element_cls=CT_Document
& name=_new_body
& method=self.creator
。执行self._add_to_class
的后,CT_Document类签名变化如下:
self._add_inserter
_add_inserter方法封装了_insert_child函数——为父节点插入一个子节点。为XML元素节点插入子节点的能力继承自lxml.etree.ElementBase。
def _add_inserter(self):"""Add an ``_insert_x()`` method to the element class for this child element."""def _insert_child(obj: BaseOxmlElement, child: BaseOxmlElement):obj.insert_element_before(child, *self._successors)return child_insert_child.__doc__ = ("Return the passed ``<%s>`` element after inserting it as a chil""d in the correct sequence." % self._nsptagname)self._add_to_class(self._insert_method_name, _insert_child)
执行完self._add_to_class
方法后,其中self._insert_method_name="_insert_body"
,CT_Document签名中就包含新的方法“_insert_body”:
self._add_adder
self._add_adder方法本质是“self._add_creator”与“self._add_inserter”二者的结合。self._add_adder方法封装了**_add_child函数**
def _add_adder(self):"""Add an ``_add_x()`` method to the element class for this child element."""def _add_child(obj: BaseOxmlElement, **attrs: Any):new_method = getattr(obj, self._new_method_name)child = new_method()for key, value in attrs.items():setattr(child, key, value)insert_method = getattr(obj, self._insert_method_name)insert_method(child)return child_add_child.__doc__ = ("Add a new ``<%s>`` child element unconditionally, inserted in t""he correct sequence." % self._nsptagname)self._add_to_class(self._add_method_name, _add_child)
_add_child函数首先创建一个空的子节点,然后将“attr”属性字典写入到新建的空子节点,并将新建的子节点插入到目标父节点、返回新建的子节点。执行完self._add_to_class(self._add_method_name, _add_child)
,其中self._add_method_name="_add_body"
后,CT_Document多自动添加了一个新方法“_add_body”:
self._add_get_or_adder
"self._add_get_or_adder"方法对“get_or_add_child”函数进行了封装——如果父节点包含目标子节点,则直接取出目标子节点;如果不包含则新建一个目标子节点并返回,新建目标子节点依赖之前的“self._add_method_name”方法,即“self._add_body”
def _add_get_or_adder(self):"""Add a ``get_or_add_x()`` method to the element class for this childelement."""def get_or_add_child(obj: BaseOxmlElement):child = getattr(obj, self._prop_name)if child is None:add_method = getattr(obj, self._add_method_name)child = add_method()return childget_or_add_child.__doc__ = ("Return the ``<%s>`` child element, newly added if not present.") % self._nsptagnameself._add_to_class(self._get_or_add_method_name, get_or_add_child)
self._get_or_add_method_name="get_or_add_body"
, 执行完“self._add_to_class()”,CT_Document就自动添加了一个新的方法:
self.add_remover
"self.add_remover"方法封装了“_remove_child”函数——该函数根据限定性标签名称,从父节点中删除目标子节点。元素节点中删除子节点的能力继承自lxml.etree.ElementBase.
def _add_remover(self):"""Add a ``_remove_x()`` method to the element class for this child element."""def _remove_child(obj: BaseOxmlElement):obj.remove_all(self._nsptagname)_remove_child.__doc__ = ("Remove all ``<%s>`` child elements.") % self._nsptagnameself._add_to_class(self._remove_method_name, _remove_child)
self._remove_method_name="_remove_body"
, 执行完“self._add_to_class()”,CT_Document就自动添加了一个新的方法:
小结
在python-docx子库oxml中,虽然在源码中并未直接定义诸多元素类对子节点元素管理的增删改查方法。但是通过利用Python元类、类继承、以及简洁直观的代码模式设计,为诸多新创建的元素类,如CT_Document,自动添加了对子元素节点的增删改查方法。这种利用Python元类来管理类方法自动创建的模式值得学习。
相关文章:
oxml中创建CT_Document类
概述 本文基于python-docx源码,详细记录CT_Document类创建的过程,以此来加深对Python中元类、以及CT_Document元素类的认识。 元类简介 元类(MetaClass)是Python中的高级特性。元类是什么呢?Python是面向对象编程…...
YARN 集群
一、集群角色 1.1 概述 Apache Hadoop YARN是一个标准的Master/Slave集群(主从架构)。其中ResourceManager(RM) 为Master, NodeManager(NM) 为 Slave。常见的是一主多从集群,也可以…...
电机控制的数字化升级:基于DSP和FPGA的仿真与实现
数字信号处理器(DSP,Digital Signal Processor)在工业自动化领域的应用日益广泛。DSP是一种专门用于将模拟信号转换成数字信号并进行处理的技术,能够实现信号的数字滤波、重构、调制和解调等多项功能,确保信号处理的精…...
homework 2025.01.11 math 6
homework 2025.01.11 math 6 小学6年级数学...
【会话详解】
会话详解 概述 会话: 用户通过浏览器访问多个Web资源的过程,从打开浏览器开始访问特定网站,直到关闭浏览器的过程称为会话(Session)。会话管理是Web应用中跟踪和存储用户状态的重要机制。 有状态会话: …...
Unity 的 Vector3 与 Babylon.js 的 Vector3:使用上的异同
在 3D 开发中,向量是不可或缺的数学工具,用于表示位置、方向、速度等物理量。Unity 和 Babylon.js 都提供了 Vector3 类来处理三维向量,但它们在实现和使用上有一些异同。本文将详细对比 Unity 的 Vector3 和 Babylon.js 的 Vector…...
【2024年华为OD机试】(A卷,100分)- 单词倒序(Java JS PythonC/C++)
一、问题描述 题目描述 输入单行英文句子,里面包含英文字母,空格以及,.?三种标点符号,请将句子内每个单词进行倒序,并输出倒序后的语句。 输入描述 输入字符串S,S的长度 1 ≤ N ≤ 100 输出描述 输出倒序后的字…...
芯片:CPU和GPU有什么区别?
CPU(中央处理器)和GPU(图形处理单元)是计算机系统中两种非常重要的处理器,它们各自有不同的设计理念、架构特点以及应用领域。下面是它们之间的一些主要差异: 1. 设计目的与应用领域 CPU:设计…...
springboot整合mysql
1.首先在pom.xml中添加依赖: <!-- MySQL Driver --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- Druid连接池 -->…...
复合机器人助力手机壳cnc加工向自动化升级
在当今竞争激烈的制造业领域,如何提高生产效率、降低成本、提升产品质量,成为众多企业面临的关键挑战。尤其是在手机壳 CNC 加工这一细分行业,随着市场需求的持续增长,对生产效能的要求愈发严苛。而复合机器人的出现,正…...
深入浅出负载均衡:理解其原理并选择最适合你的实现方式
负载均衡是一种在多个计算资源(如服务器、CPU核心、网络链接等)之间分配工作负载的技术,旨在优化资源利用率、提高系统吞吐量和降低响应时间。负载均衡的实现方式多种多样,以下是几种常见的实现方式: 1. 硬件负载均衡&…...
征程 6X release版本内核模块安全加载
1.概述 征程 6X 系统在 release 编译时支持内核模块签名验证,仅加载使用正确密钥进行数字签名的内核模块。禁止加载未签名的内核模块或使用错误密钥签名的内核模块,客户需要替换成自己的 key 进行签名。 模块签名启用后,Linux 内核将仅加载…...
uni-app的学习
uni-app 有着跨平台支持、丰富的插件和生态系统、高性能、集成开发工具HBuilderX的配合使用。允许使用者仅通过一套代码发布到多平台使用。 uni-app官网 uni-app 是一个适合开发跨平台移动应用和小程序的框架,能够大幅提高开发效率。 一、了解 1.1 工具准备 从Git…...
国产信创实践(国能磐石服务器操作系统CEOS +东方通TongHttpServer)
替换介绍: 国能磐石服务器操作系统CEOS 对标 Linux 服务器操作系统(Ubuntu, CentOS) 东方通TongHttpServer 对标 Nginx 负载均衡Web服务器 第一步: 服务器安装CEOS映像文件,可直接安装,本文采用使用VMware …...
前端实时显示当前在线人数的实现
实时显示当前在线人数的实现 本文档提供了在网页上实时显示当前在线人数的多种实现方法,包括使用 WebSocket 实现实时更新和轮询方式实现非实时更新。 方法一:使用 WebSocket 实现实时更新 服务器端设置 通过 Node.js 和 WebSocket 库(如 …...
为AI聊天工具添加一个知识系统 之27 支持边缘计算设备的资源存储库及管理器
本文问题 现在我们回到 ONE/TWO/TREE 的资源存储库 的设计--用来指导 足以 支持 本项目(为AI聊天工具增加一套知识系统)的 核心能力 “语言处理” 中 最高难度系数的“自然语言处理” 中最具挑战性的“含糊性” 问题的解决。--因为足以解决 自然语言中最…...
继续坚持与共勉
经过期末考试后,又要开始学习啦。 当时一直在刷算法题就很少写博客了,现在要继续坚持写博客,将每天对于题的感悟记录下来。 同时我将会在学习Linux操作系统,对于过去学习的内容进行回顾!! 在此ÿ…...
PHP的扩展Imagick的安装
windows下的安装 下载:Imagick扩展 PECL :: Package :: imagick 3.7.0 for Windows 下载:ghostscript(PDF提取图片时用到,不处理PDF可以不安装) Ghostscript : Downloads 安装扩展 Imagick解压后&…...
【2024年华为OD机试】 (A卷,100分)- 租车骑绿岛(Java JS PythonC/C++)
一、问题描述 题目描述 部门组织绿岛骑行团建活动。租用公共双人自行车,每辆自行车最多坐两人,最大载重 M。 给出部门每个人的体重,请问最多需要租用多少双人自行车。 输入描述 第一行两个数字 m、n,分别代表自行车限重&#…...
Solidity入门: 函数
函数 Solidity语言的函数非常灵活,可以进行各种复杂操作。在本教程中,我们将会概述函数的基础概念,并通过一些示例演示如何使用函数。 我们先看一下 Solidity 中函数的形式: function <function name>(<parameter types>) {in…...
1、docker概念和基本使用命令
docker概念 微服务:不再是以完整的物理机为基础的服务软件,而是借助于宿主机的性能。以小量的形式,单独部署的应用。 docker:是一个开源的应用容器引擎,基于go语言开发的,使用时apache2.0的协议。docker是…...
【Python】深入Python元类:动态生成类与对象的艺术
在Python中,元类(Metaclass)是一个强大且高级的特性,允许开发者在类创建时控制其行为与属性。通过元类,开发者可以动态生成类和对象,实现自定义的类行为,进而增强代码的灵活性和可扩展性。本文将…...
数字孪生可视化在各个行业的应用场景
数字孪生技术,作为新一代信息技术的集大成者,正在深刻改变着我们对物理世界的认知和管理方式。本文将探讨数字孪生可视化在不同行业的应用场景,以及它们如何赋能行业数字化转型。 1. 智慧城市与交通 在智慧城市领域,数字孪生技术…...
CES Asia 2025科技盛宴,AI智能体成焦点
2025第七届亚洲消费电子技术展(CES Asia赛逸展)将在北京拉开帷幕,AI智能体有望成为展会的核心亮点。 深圳市人工智能行业协会发文表示全力支持CES Asia 2025(赛逸展),称其为人工智能领域的创新发展提供了强…...
【第04阶段-机器学习深度学习篇-1-深度学习基础-深度学习介绍】
1 深度学习概念 深度学习是基于机器学习延伸出来的一个新的领域,由以人大脑结构为启发的神经网络算法为起源加之模型结构深度的增加发展,并伴随大数据和计算能力的提高而产生的一系列新的算法。 2 深度学习发展 其概念由著名科学家Geoffrey Hinton等人…...
android framework.jar 在应用中使用
在开发APP中,有时会使用系统提供的framework.jar 来替代 android.jar, 在gradle中配置如下: 放置framework.jar 依赖配置 3 优先级配置 gradle.projectsEvaluated {tasks.withType(JavaCompile) {Set<File> fileSet options.bootstrapClasspat…...
带格式 pdf 翻译
支持 openAI 接口,国内 deepseek 接口兼容 openAI 接口, deepseek api 又非常便宜 https://pdf2zh.com/ https://github.com/Byaidu/PDFMathTranslate...
Flutter项目适配鸿蒙
Flutter项目适配鸿蒙 前言Flutter项目适配鸿蒙新工程直接支持ohos构建新项目编译运行 适配已有的Flutter项目 前言 目前市面上使用Flutter技术站的app不在少数,对于Flutter的项目,可能更多的是想直接兼容Harmonyos,而不是直接在重新开发一个…...
轻量自高斯注意力机制LSGAttention模型详解及代码复现
模型背景 近年来,卷积神经网络(CNN)在高光谱图像分类领域取得了显著进展。然而,CNN面临 长距离关系建模 和 计算成本 增加的挑战。为解决这些问题,研究人员提出了基于 轻量自高斯注意(Light Self-Gaussian-Attention, LSGA) 机制的视觉转换器(Vision Transformer, VIT),旨…...
vue事件对象$event
事件参数可以获取event对象和通过事件传递数据 获取 event 对象 <template><h1>Hello world</h1><button click"addCount">Add</button><p>{{ count }}</p> </template> <script>export default{data(){ret…...
PyCharm文档管理
背景:使用PyCharmgit做文档管理 需求:需要PyCharm自动识别docx/xslx/vsdx等文件类型,并在PyCharm内点击文档时唤起系统内关联应用(如word、excel、visio) 设置步骤: 1、file -》 settings -》file types 2、在Files opened i…...
Windows下调试Dify相关组件(2)--后端Api
1.部署依赖的服务(代码最外层的docker目录) 1.1 将middleware.env.example复制,并改名为middleware.env。 1.2 查看docker-compose.middleware.yaml,有5个服务 db:postgres数据库。 redis:redis缓存。 sa…...
Flask----前后端不分离-登录
文章目录 扩展模块flask-wtf 的简单使用定义用户数据模型flask-login完成用户登录 扩展模块 flask-sqlalchmy,连接数据库flask-login,处理用户的登录,认证flask-session,会话保持,默认对用户数据加密,存储…...
Group3r:一款针对活动目录组策略安全的漏洞检测工具
关于Group3r Group3r是一款针对活动目录组策略安全的漏洞检测工具,可以帮助广大安全研究人员迅速枚举目标AD组策略中的相关配置,并识别其中的潜在安全威胁。 Group3r专为红蓝队研究人员和渗透测试人员设计,该工具可以通过将 LDAP 与域控制器…...
ElasticSearch 认识和安装ES
文章目录 一、为什么学ElasticSearch?1.ElasticSearch 简介2.ElasticSearch 与传统数据库的对比3.ElasticSearch 应用场景4.ElasticSearch 技术特点5.ElasticSearch 市场表现6.ElasticSearch 的发展 二、认识和安装ES1.认识 Elasticsearch(简称 ES)2.El…...
CNN Test Data
由于数据量过大,打不开了 搞一组小的吧。收工睡觉 https://download.csdn.net/download/spencer_tseng/90256048...
git 转移文件夹
打开终端或命令行界面:首先,确保你的电脑上安装了 Git,并打开终端或命令行界面。 导航到你的仓库目录:使用 cd 命令来切换到包含你想要移动文件夹的仓库的目录。 cd /path/to/your/repository使用 git mv 命令移动文件夹&#x…...
计算机网络学习
网络安全:前端开发者必知:Web安全威胁——XSS与CSRF攻击及其防范-CSDN博客 三次握手四次挥手:前端网络---三次握手四次挥手_前端三次握手-CSDN博客 http协议和https协议的区别:前端网络---http协议和https协议的区别-CSDN博客 …...
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例
Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 : 编译之前,需要将 clang 导出到 PATH 环境变量: 如果是 Android12 执行下面这条命令 export PATH../pr…...
Java线程的异常处理:确保线程安全运行
哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云/阿里云/华为云/51CTO;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互…...
vite5.x配置https
旧版的vite直接在config里面配置https:true即可,新版的麻烦一些。 1.准备工作 需要安装openssl 下载地址:Win32/Win64 OpenSSL Installer for Windows - Shining Light Productions 找到合适的版本安装,配置好环境变量&#x…...
地下苹果(马铃薯)怎么破局?
地下苹果(马铃薯)怎么破局? 原创萨辣米哎青年杂说youth 地下苹果(马铃薯)怎么破局?https://mp.weixin.qq.com/s/zU-9pnVWxDn72D6yx5CViA 1.前言 马铃薯是重要的粮菜兼用和工业原料作物,由于其…...
ceph fs status 输出详解
ceph fs status 命令用于显示 Ceph 文件系统的状态信息,其中各列的含义如下: RANK:元数据服务器(MDS)的等级或标识符。 STATE:MDS 的当前状态,例如 active(活跃)、stan…...
phpenc加密程序源码
免费扩展加密程序,类似于sg11加密,支持单个PHP(免费)文件以及批量PHP文件(ZIP压缩包格式)源码加密的保护平台,加密后的源码文件保持原有代码结构,可以跨平台运行,可以运行…...
深入探秘 ZooKeeper:架构、设计、角色与 ZNode 全解析 前言
1.ZooKeeper 分布式锁怎么实现的? ZooKeeper 是一个高效的分布式协调服务,常用于实现分布式系统中的配置管理、命名服务、分布式锁等。下面简要介绍如何使用 ZooKeeper 实现分布式锁。 分布式锁的特性 在讨论如何实现之前,先了解分布式锁应…...
计算机图形学【绘制立方体和正六边形】
工具介绍 OpenGL:一个跨语言的图形API,用于渲染2D和3D图形。它提供了绘制图形所需的底层功能。 GLUT:OpenGL的一个工具库,简化了窗口创建、输入处理和其他与图形环境相关的任务。 使用的函数 1. glClear(GL_COLOR_BUFFER_BIT |…...
日志模块和Plus模块升级以及问题修复
文章目录 1.common-log4j2-starter1.目录2.LogAspectProperties.java 日志切面配置3.TraceProperties.java 链路追踪配置4.Log4j2AutoConfiguration.java 条件注入链路追踪过滤器 2.common-mybatis-plus-starter1.目录2.引入依赖3.SqlBeautyProperties.java 读取sql.beauty相关…...
【Bug】报错信息:Required request body is missing(包含五种详细解决方案)
大家好,我是摇光~ 遇到“Required request body is missing”错误通常意味着服务器期望在HTTP请求中包含一个请求体(body),但是实际上并没有收到。 例如: 当你在使用网页或应用程序的后台(比如一个网站或手…...
Ceph分布式存储集群,不仅仅是一个简单的对象存储解决方案
Ceph 作为 OpenStack 的存储后端 块存储(Cinder 后端) Ceph 的 RBD(RADOS Block Device)模块作为 OpenStack Cinder 服务的后端,为虚拟机提供块级别的存储资源。RBD 支持快照、克隆和恢复等功能,能够满足虚…...
6.business english--updates
能够运用一系列表达方式来提供和接收最新情况,并讨论后续行动事项。 be able to use a range of expression to give and receive updates and to discuss follow-up action items in a typical week 在平常的一周里 The company promises that the quality will …...