当前位置: 首页 > news >正文

Ansible的filter

环境

  • 控制节点:Ubuntu 22.04
  • Ansible 2.10.8
  • 管理节点:CentOS 8

filter

使用filter可以对数据做操作,比如把JSON数据转换为YAML数据,从URL中解析出hostname,提取字符串的SHA1哈希值,做数学运算,等等。可以使用Ansible特有的filter,也可以使用jinja2移植的标准filter。

因为templating发生在Ansible的控制节点,而不是目标节点,所以filter运行在控制节点,并在本地转换数据。

处理未定义变量

提供缺省值

创建文件 test1.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "Hello {{ var1 }}"

运行结果如下:

➜  temp1105_2 ansible-playbook test1.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
fatal: [192.168.1.55]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'var1' is undefined\n\nThe error appears to be in '/root/temp/temp1105_2/test1.yml': line 4, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n  tasks:\n    - name: task1\n      ^ here\n"}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

这是因为变量 var1 未定义。

为避免出错,可以使用jinja2的 default filter:

---
- hosts: alltasks:- name: task1debug:msg: "Hello {{ var1 | default('ABC') }}, {{var2 | default(\"XYZ\")}}, {{ var3 | default(123) }}"

其中:

  • var1 default值是单引号引起来的字符串
  • var2 default值是双引号引起来的字符串,所以用 \ 来转义
  • var3 default值是数值,不需要用引号

运行结果如下:

➜  temp1105_2 ansible-playbook test1.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "Hello ABC, XYZ, 123"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

注:对于role,也可以在其 defaults/main.yml 文件里给该role的变量定义缺省值。

如果原值evaluate为false或者空字符串,则使用default时,需要将其第二个参数设置为true(默认值是false):

......msg: "aaa {{ '' | default('empty string', true) }} bbb"
......

运行结果如下:

......"msg": "aaa empty string bbb"
......

注:如果不加第二个参数,则不会替换为缺省值。

变量为空值

创建文件 test2.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "aaa {{ item.var1 }} bbb {{ item.var2 | default(omit) }}"loop:- var1: "Tom"var2: 20- var1: "Jerry"

其中,item1指定了 var1var2 ,而item2只指定了 var1

运行结果如下:

➜  temp1105_2 ansible-playbook test2.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item={'var1': 'Tom', 'var2': 20}) => {"msg": "aaa Tom bbb 20"
}
ok: [192.168.1.55] => (item={'var1': 'Jerry'}) => {"msg": "aaa Jerry bbb __omit_place_holder__ae2509bf44427378895b86e1e65511fbaaf58727"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可见,指定了 default(omit) ,则变量默认值为空(若打印其值,则输出一个占位符)。

注:对于链式filter,官网上说,要用 "{{ foo | default(None) | <some_filter> or omit }}" 的形式,比如:

msg: " {{ var1 | default(None) | lower or omit }}"

运行结果如下:

    "msg": " none"

但我试了一下,如果不这么做,比如:

msg: " {{ var1 | default(omit) | lower }}"

也不报错,运行结果如下:

    "msg": " __omit_place_holder__2212ea218f1e07f0070e5184cf11ebf71e3e5e9e"

变量必须有值

如果配置了 DEFAULT_UNDEFINED_VAR_BEHAVIORfalse ,则变量允许为空值。此时,如果想要强制变量不得为空值,则可以使用 mandatory filter,比如:

{{ var1 | mandatory }}

根据不同值true/false/null做判断

注: ternary三元 的意思。

创建文件 test6.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ (var1 == 'a') | ternary('111', '222') }}"vars:- var1: 'a'  

本例中,由于 var1 == 'a' 是true,所以会打印 111

➜  temp1105_2 ansible-playbook test6.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "111"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

创建文件 test7.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ var1 | ternary('111', '222', omit) }}"vars:- var1: 'abc'- name: task2debug:msg: "{{ var2 | ternary('111', '222', omit) }}"vars:- var2: false- name: task3debug:msg: "{{ var3 | ternary('111', '222', omit) }}"vars:- var3: null

运行结果如下:

➜  temp1105_2 ansible-playbook test7.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "111"
}TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "222"
}TASK [task3] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "Hello world!"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
  • var1 有值且不等于 false ,表示true
  • var2 其值为 false (注意没有引号,否则是字符串),表示false
  • var3 其值为 null ,注意打印出了 Hello world!

管理数据类型

检测数据类型

创建文件 test8.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ 'abc' | type_debug }}, {{ 123 | type_debug }}, {{ 0.5 | type_debug }}, {{ true | type_debug }}"

运行结果如下:

➜  temp1105_2 ansible-playbook test8.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "str, int, float, bool"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0    

可见:

  • 'abc' 类型为 str
  • 123 类型为 int
  • 0.5 类型为 float
  • true 类型为 bool

强制类型转换

创建文件 test9.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ var1 | int | type_debug }}, {{ var2 | float | type_debug }}, {{ var3 |bool | type_debug }}, {{ var4 | string | type_debug }}"vars:- var1: '123'- var2: '0.5'- var3: 'true'- var4: 456

运行结果如下:

➜  temp1105_2 ansible-playbook test9.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "int, float, bool, str"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

JSON和YAML

  • to_json :转换为JSON格式
  • to_nice_json :转换为可读的JSON格式(加上换行,缩进等)
  • to_yaml :转换为YAML格式
  • to_nice_yaml :转换为可读的YAML格式(加上换行,缩进等)

创建文件 test12.yml 如下:

---
- hosts: alltasks:- name: task1template:src: /tmp/src1dest: /tmp/dest1- name: task2template:src: /tmp/src2dest: /tmp/dest2- name: task3template:src: /tmp/src3dest: /tmp/dest3- name: task4template:src: /tmp/src4dest: /tmp/dest4

/tmp/src1 如下:

{{ ansible_facts['default_ipv4'] | to_json }}

/tmp/src2 如下:

{{ ansible_facts['default_ipv4'] | to_nice_json }}

/tmp/src3 如下:

{{ ansible_facts['default_ipv4'] | to_yaml }}

/tmp/src4 如下:

{{ ansible_facts['default_ipv4'] | to_nice_yaml }}

运行结果如下:

➜  temp1105_2 ansible-playbook test12.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
changed: [192.168.1.55]TASK [task2] ***************************************************************************************
changed: [192.168.1.55]TASK [task3] ***************************************************************************************
changed: [192.168.1.55]TASK [task4] ***************************************************************************************
changed: [192.168.1.55]PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

运行结束后,到目标机器上查看。

/tmp/dest1 如下:

{"gateway": "192.168.1.1", "interface": "ens33", "address": "192.168.1.55", "broadcast": "192.168.1.255", "netmask": "255.255.255.0", "network": "192.168.1.0", "macaddress": "00:0c:29:12:a6:b7", "mtu": 1500, "type": "ether", "alias": "ens33"}

/tmp/dest2 如下:

{"address": "192.168.1.55","alias": "ens33","broadcast": "192.168.1.255","gateway": "192.168.1.1","interface": "ens33","macaddress": "00:0c:29:12:a6:b7","mtu": 1500,"netmask": "255.255.255.0","network": "192.168.1.0","type": "ether"
}

/tmp/dest3 如下:

{address: 192.168.1.55, alias: ens33, broadcast: 192.168.1.255, gateway: 192.168.1.1,interface: ens33, macaddress: '00:0c:29:12:a6:b7', mtu: 1500, netmask: 255.255.255.0,network: 192.168.1.0, type: ether}

/tmp/dest4 如下:

address: 192.168.1.55
alias: ens33
broadcast: 192.168.1.255
gateway: 192.168.1.1
interface: ens33
macaddress: 00:0c:29:12:a6:b7
mtu: 1500
netmask: 255.255.255.0
network: 192.168.1.0
type: ether

注: to_yamlto_nice_yaml ,默认每行包含80个字符(当超过80字符后,遇到空格就会换行),可以指定 width 选项,比如:

{{ ansible_facts['default_ipv4'] | to_yaml(width=500) }}

结果如下:

{address: 192.168.1.55, alias: ens33, broadcast: 192.168.1.255, gateway: 192.168.1.1, interface: ens33, macaddress: '00:0c:29:12:a6:b7', mtu: 1500, netmask: 255.255.255.0, network: 192.168.1.0, type: ether}

可以指定 indent 选项(默认值貌似是4),比如:

{{ ansible_facts['default_ipv4'] | to_nice_json(indent=8) }}

结果如下:

{"address": "192.168.1.55","alias": "ens33","broadcast": "192.168.1.255","gateway": "192.168.1.1","interface": "ens33","macaddress": "00:0c:29:12:a6:b7","mtu": 1500,"netmask": "255.255.255.0","network": "192.168.1.0","type": "ether"
}

可见缩进值变为8了。

  • from_json :读取已知的JSON数据
  • from_yaml :读取已知的YAML数据

在目标机器上创建 json1.json 如下:

{"Name": "Tom","Age": 20,"Sports":["Football", "Swimming"]
}

在目标机器上创建 yaml1.yml 如下:

Name: Tom
Age: 20
Sports:- Football- Swimming

创建文件 test14.yml 如下:

---
- hosts: alltasks:- name: task1shell: cat /tmp/json1.jsonregister: result1- name: task2debug:msg: "{{ result1.stdout | type_debug }}"- name: task3debug:msg: "{{ result1.stdout | from_json | type_debug }}"- name: task4shell: cat /tmp/yaml1.ymlregister: result2- name: task5debug:msg: "{{ result2.stdout | type_debug }}"- name: task6debug:msg: "{{ result2.stdout | from_yaml | type_debug }}"

运行结果如下:

➜  temp1105_2 ansible-playbook test14.ymlPLAY [all] *****************************************************************************************TASK [Gathering Facts] *****************************************************************************
ok: [192.168.1.55]TASK [task1] ***************************************************************************************
changed: [192.168.1.55]TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "AnsibleUnsafeText"
}TASK [task3] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "dict"
}TASK [task4] ***************************************************************************************
changed: [192.168.1.55]TASK [task5] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "AnsibleUnsafeText"
}TASK [task6] ***************************************************************************************
ok: [192.168.1.55] => {"msg": "dict"
}PLAY RECAP *****************************************************************************************
192.168.1.55               : ok=7    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

可见,如果不加 from_jsonfrom_yaml ,则读取的是字符串( AnsibleUnsafeText ),加上from_jsonfrom_yaml ,则读取为 dict

随机数

创建文件 test15.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ 60 | random }}"

运行结果如下:

    "msg": "4"

多次运行,结果也不同。

注意:取值范围是0到60,左闭右开。

如果想指定起始值,可以用 start 选项:

        msg: "{{ 60 | random(start=55) }}"

则取值范围是55到60,左闭右开。

如果要求取值是特定值的整倍数,可以用 step 选项:

        msg: "{{ 60 | random(step=20) }}"

则取值只能是0或20或40。

如果想在多个目标机器上各自产生不同的随机数,但要求每个机器上的随机数多次运行结果不变(幂等性),则可以添加 seed 选项,使用该种子来产生随机数,注意seed的值不要变:

        msg: "{{ 60 | random(seed=inventory_hostname) }}"
    "msg": "50"

多次运行,产生的随机数保持不变。

数学运算

  • log
  • pow
  • root
  • abs
  • round

创建文件 test16.yml 如下:

---
- hosts: alltasks:- name: task1debug:msg: "{{ 100 | log(10) }}, {{ 2 | pow(10) }}, {{ 216 | root(3) }}, {{ -1.5 | abs }}, {{ 12.34 | round }}"

运行结果如下:

    "msg": "2.0, 1024.0, 5.999999999999999, 1.5, 12.0"

注释

comment 将内容注释。默认的注释符是 # ,可以指定不同语言来做注释。

创建文件 test17.yml 如下:

---
- hosts: alltasks:- name: task1template:src: /tmp/src1dest: /tmp/dest1- name: task2template:src: /tmp/src2dest: /tmp/dest2- name: task3template:src: /tmp/src3dest: /tmp/dest3- name: task4template:src: /tmp/src4dest: /tmp/dest4- name: task5template:src: /tmp/src5dest: /tmp/dest5

创建文件 /tmp/src1 如下:

{{ 'aaa' | comment }}

创建文件 /tmp/src2 如下:

{{ 'bbb' | comment('c') }}

创建文件 /tmp/src3 如下:

{{ 'ccc' | comment('cblock') }}

创建文件 /tmp/src4 如下:

{{ 'ddd' | comment('erlang') }}

创建文件 /tmp/src5 如下:

{{ 'eee' | comment('xml') }}

运行结束后,到目标机器上查看:

/tmp/dest1 如下:

#
# aaa
#

/tmp/dest2 如下:

//
// bbb
//

/tmp/dest3 如下:

/*** ccc**/

/tmp/dest4 如下:

%
% ddd
%

/tmp/dest5 如下:

<!---- eee-
-->

字符串操作

  • quote :给值加上引号
      shell: echo {{ var1 | quote }} > /tmp/a.txtvars:var1: "a\nb\nc"

运行结束后,目标机器 /tmp/a.txt 如下:

a
b
c

如果没有 quote ,则会报错。

  • join :连接字符串
      debug:msg: "{{ ['a', 'b', 'c'] | join(' ') }}"

运行结果如下:

    "msg": "a b c"
  • split :切割字符串
      debug:msg: "{{ 'a,b,c' | split(',') }}"

注:需要升级到2.11,我用的是2.10,会报错。

  • b64encode :Base64 encode
      debug:msg: "{{ 'abcdefg' | b64encode }}"

运行结果如下:

    "msg": "YWJjZGVmZw=="
  • b64decode :Base64 decode
      debug:msg: "{{ 'YWJjZGVmZw==' | b64decode }}"

运行结果如下:

    "msg": "abcdefg"

UUID

  • to_uuid :创建UUID
      debug:msg: "{{ 'abcdefg' | to_uuid }}"

运行结果如下:

    "msg": "aeb26d4d-43ec-587e-b3a8-67b6ca88a4df"

参考

  • https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html
  • https://jinja.palletsprojects.com/en/latest/templates

相关文章:

Ansible的filter

环境 控制节点&#xff1a;Ubuntu 22.04Ansible 2.10.8管理节点&#xff1a;CentOS 8 filter 使用filter可以对数据做操作&#xff0c;比如把JSON数据转换为YAML数据&#xff0c;从URL中解析出hostname&#xff0c;提取字符串的SHA1哈希值&#xff0c;做数学运算&#xff0c…...

Qt绘制各种图表

绘制柱状图&#xff1a; void MainWindow::iniBarChart() { //柱状图初始化QChart *chart new QChart(); //创建chartchart->setTitle("Barchart演示");chart->setAnimationOptions(QChart::SeriesAnimations);ui->chartViewBar->setChart(chart); //为…...

【科研新手指南4】ChatGPT的prompt技巧 心得

ChatGPT的prompt心得 写在最前面chatgpt咒语1&#xff08;感觉最好用的竟然是这个&#xff0c;简单方便快捷&#xff0c;不需要多轮对话&#xff09;chatgpt思维链2&#xff08;复杂任务更适用&#xff0c;简单任务把他弄复杂了&#xff09;机理chatgpt完整咒语1&#xff08;感…...

龙蜥社区联合浪潮信息发布《eBPF技术实践白皮书》(附下载链接)

随着 eBPF 技术的高速发展&#xff0c;eBPF 已成为 Linux 内核顶级子系统&#xff0c;并扩展到内核网络、存储、内存、调度和安全等子模块。这种可编程底座内核框架构建了全系统&#xff0c;是云计算、运维和安全等领域技术创新的基础。 龙蜥社区在 eBPF 领域进行了广泛的实践…...

屏幕截图软件 Snagit mac中文版软件特点

Snagit mac是一款屏幕截图和视频录制软件&#xff0c;它可以帮助用户快速捕捉屏幕上的任何内容&#xff0c;并将其编辑、标注和共享。 Snagit mac软件特点 多种截图模式&#xff1a;支持全屏截图、窗口截图、区域截图、延时截图等多种截图模式&#xff0c;满足不同用户的需求。…...

四、Ribbon负载均衡

目录 一、负载均衡流程 1、我通过浏览器直接访问userservice/user/1&#xff0c;无法访问&#xff0c;说明是负载均衡做了相应的处理 2、我们来看一下代码中负载均衡的流程是怎样的 3、图像流程 二、负载均衡策略 1、修改负载均衡策略 &#xff08;方式一&#xff09; &a…...

【Git】第二篇:基本操作(创建本地仓库)

我们知道&#xff0c;git是一个版本控制器&#xff0c;可以帮我们控制管理电脑上所有格式的文档。 而我们需要使用git管理文件的时候&#xff0c;我们必须将这些文件放到git仓库中&#xff0c;只有在git仓库中的文件才可以被我们的git追踪管理 创建本地仓库 创建本地仓库是需…...

vuex——重置vuex数据

需求描述 登出系统时&#xff0c;需将 vuex 中存储的数据&#xff0c;恢复为最初的默认状态。 实现方法 通过 replaceState 方法&#xff0c;将最初的 vuex 的 state 数据作为参数传入即可 完整代码范例 src\store\index.js import Vue from "vue"; import Vuex fro…...

WebSphere Liberty 8.5.5.9 (三)

WebSphere Liberty 8.5.5.9 将资源先下载&#xff0c;后期本地安装 下载 passwordUtilities-1.0 D:\wlp-webProfile7-java8-8.5.5.9\wlp\bin>installUtility find password 正在建立与已配置存储库的连接... 此过程可能要花几分钟完成。已成功连接至所有已配置的存储库。…...

如何区分一个项目是react还react native

要区分一个项目是 React 还是 React Native&#xff0c;你可以关注以下几个方面&#xff1a; 项目目录结构&#xff1a;React 和 React Native 项目通常具有不同的目录结构。React 项目中的源代码通常位于一个名为 "src" 或 "app" 的文件夹中&#xff0c;包…...

网易有道开源语音合成引擎“易魔声”

概述 11 月 10 日&#xff0c;网易有道正式上线“易魔声”开源语音合成&#xff08;TTS&#xff09;引擎&#xff0c;所有用户可免费在开源社区 GitHub 进行下载使用&#xff0c;通过其提供的 web 界面及批量生成结果的脚本接口&#xff0c;轻松实现音色的情感合成与应用。 据…...

[量子计算与量子信息] 2.1 线性代数

2.1 线性代数 符号对照表 量子力学中&#xff0c;向量使用 ∣ ψ ⟩ \ket \psi ∣ψ⟩ (ket)来表示&#xff0c;可以理解为一个列向量。其对偶向量为 ⟨ ψ ∣ \bra \psi ⟨ψ∣ &#xff0c;可以理解为行向量。 向量空间中零向量直接用 0 0 0 表示&#xff0c; ∣ 0 ⟩ \…...

【PG】PostgreSQL 目录结构

目录 1 软件安装目录 2 数据文件目录 base/&#xff1a;存储每个数据库的基本数据文件 global/&#xff1a;包含了全局性质的系统表空间文件 pg_tblspc/&#xff1a;包含了表空间的符号链接 pg_twophase/&#xff1a;包含了两阶段提交中使用的文件 pg_stat_tmp/&#xff…...

H5游戏源码分享-超级染色体小游戏

H5游戏源码分享-超级染色体小游戏 游戏玩法 不断地扩大发展同颜色的色块 用最少的步数完成游戏 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport"content"widthdevice-width,user-scalableno,init…...

NOIP 2017 宝藏----Java题解

目录 NOIP 2017 宝藏 题目描述 输入描述: 输出描述: 输入 输出 说明 输入 输出 说明 备注: 代码实现&#xff1a; NOIP 2017 宝藏 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 262144K&#xff0c;其他语言524288K 64bit IO For…...

数据结构和算法的重要性

目录 1.什么是数据结构&#xff1f; 2.什么是算法&#xff1f; 3.数据结构和算法的重要性 4.如何学好数据结构和算法 1.什么是数据结构&#xff1f; 数据结构(Data Structure)是计算机存储、组织数据的方式&#xff0c;指相互之间存在一种或多种特定关系的数据元素的集合 …...

2023.11.10 信息学日志

2023.11.10 信息学日志 1. CF1613E Crazy Robot题目描述题目概况思路点拨 1. CF1613E Crazy Robot 题目描述 https://www.luogu.com.cn/problem/CF1613E 题目概况 来源&#xff1a;Codeforces 洛谷难度&#xff1a; 绿题 \color{green}绿题 绿题 CF难度&#xff1a; 2000…...

0基础学习VR全景平台篇第120篇:极坐标处理接缝 - PS教程

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 紧跟上节课&#xff0c;我们已经学会了怎么利用PS蒙版工具来对航拍全景图补天。但是在后续工作学习中&#xff0c;我们会遇到天空这部分存在部分接缝的问题&#xff0c;如图&…...

Python---综合案例:通讯录管理系统---涉及点:列表、字典、死循环

需求&#xff1a; 开个一个通讯录的管理系统&#xff0c;主要用于实现存储班级中同学的信息&#xff08;姓名、年龄、电话&#xff09; 涉及点&#xff1a;列表、字典、死循环 相关链接&#xff1a;Python--列表及其应用场景---增、删、改、查。-CSDN博客 Python---字典---…...

Vite探索:构建、启程、原理、CSS艺术与插件魔法

文章目录 1 构建工具1.1 什么是构建工具1.2 主流构建工具1.3 vite相较于webpack的优势 2 vite启动项目初体验2.1 你必须要理解的vite脚手架和vite2.2 vite开箱即用2.3 vite的预加载2.4 vite配置文件处理细节2.5 vue环境变量配置 3 vite 原理篇3.1 vite是怎么让浏览器可以识别.v…...

Office RibbonX Editor:让Office界面定制变得像搭积木一样简单

Office RibbonX Editor&#xff1a;让Office界面定制变得像搭积木一样简单 【免费下载链接】office-ribbonx-editor An overhauled fork of the original Custom UI Editor for Microsoft Office, built with WPF 项目地址: https://gitcode.com/gh_mirrors/of/office-ribbon…...

从社交关系到分子结构:图解GCN(图卷积网络)到底在‘看’什么?

从社交关系到分子结构&#xff1a;图解GCN&#xff08;图卷积网络&#xff09;到底在‘看’什么&#xff1f;想象一下&#xff0c;你刚搬到一个新社区&#xff0c;想快速了解周围的邻居。最直接的方式是什么&#xff1f;不是挨家挨户敲门&#xff0c;而是通过社区活动认识几位关…...

警惕!AI正在悄悄重构全球攻防格局

警惕&#xff01;AI 正在悄悄重构全球攻防格局 热点聚焦 AI重构网络安全&#xff1a;全球巨头加速布局 2026年5月&#xff0c;全球网络安全领域迎来重大变革&#xff0c;AI技术正在重塑攻防格局。OpenAI发布专为网络安全防御打造的集成化AI平台Daybreak&#xff0c;将安全防…...

浏览器指纹识别机制深度剖析与反识别技术实现

一、浏览器指纹技术基础认知1.1 浏览器指纹的核心定义在数字化时代&#xff0c;每一台接入互联网的设备都会留下独特的数字标识&#xff0c;浏览器指纹便是其中最关键的识别凭证之一。浏览器指纹是网站通过 JavaScript 脚本、HTTP 请求头、硬件接口调用等多种技术手段&#xff…...

告别多头对接!DMXAPI 为企业打造国产大模型 “统一入口”

一、企业 AI 落地的普遍痛点&#xff1a;被接口和平台消耗的成本在企业数字化转型的浪潮中&#xff0c;AI 大模型已经成为标配&#xff0c;但很多企业在落地时&#xff0c;都会陷入一个共同的困境&#xff1a;为了满足不同业务场景的需求&#xff0c;需要同时对接 DeepSeek、阿…...

大厂校招变了:AI 能力正在进入笔试和面试

最近不少同学投递校招时&#xff0c;应该已经发现一个变化&#xff1a; 以前 JD 里写的是“熟悉 Python / Java / SQL / Office 优先”。 现在越来越多岗位开始出现新的描述&#xff1a; “熟练使用 AI 工具者优先” “了解大模型应用者优先” “具备 AI 辅助编程经验优先” “…...

基于窗口比较器与晶体管逻辑的可编程非线性电压指示器设计

1. 项目概述&#xff1a;打造一个可编程的“移动光点”电压指示器在电子制作和仪器仪表领域&#xff0c;我们经常需要一个直观的电压指示器。经典的LM3914点/条图显示驱动芯片大家都很熟悉&#xff0c;它能把一个模拟电压信号转换成10个LED的点亮状态&#xff0c;形成移动的光点…...

Charles弱网测试六维参数实战:从丢包率到DNS延迟的精准复现

1. 为什么弱网测试不能只靠“模拟3G”按钮点一下就完事做移动端或Web前端的同学&#xff0c;大概率都听过这句话&#xff1a;“上线前跑一遍Charles&#xff0c;切个2G网络测下加载。”——听起来很专业&#xff0c;实际一查日志&#xff0c;发现90%的团队连Charles的Throttlin…...

框架组件识别:从版本号到利用链的渗透实战指南

1. 这不是“扫个版本号”那么简单&#xff1a;框架组件识别在真实渗透中的战略定位 很多人看到“框架组件识别”&#xff0c;第一反应是跑个whatweb、wappalyzer&#xff0c;截图发报告里写一句“识别到Spring Boot 2.6.3”&#xff0c;就算交差了。我干这行十多年&#xff0c;…...

2026年新能源人才全球本地化策略

导读&#xff1a;报告基于领英行业洞察&#xff0c;聚焦 2026 年全球新能源行业发展格局、中国企业出海现状、人才供需痛点及全球化人才本地化落地策略&#xff0c;为新能源企业海外人才招聘、培养与组织管理提供完整解决方案。关注公众号&#xff1a;【互联互通社区】&#xf…...