本文主角是一个SaaS模式的“后台发货系统”,对接美团等O2O平台的订单。
目的是将各销售渠道的订单统一管理,完成发货。
既然统一发货,就少不了做统一的库存同步到销售渠道的机制。这样才能确保各平台数据互通,良性运营。
本次案例就来自库存价格同步机制这块的优化。
01. 产品模型整个业务模型大概是这样的:
该图表自下往上,分别是:
1)最下是“商户WMS”:作为真实的门店和门店商品库存、价格的来源。(因为是O2O,所以库存就来自实体门店)。
2)图中间是SaaS系统的“商户商品后台”:生成平台+线上门店+商品维度的数据清单,以衔接下端WMS和上端平台后台的数据。
3)最上面是O2O平台的后台:各渠道后台通过统一接口,统一在发货系统中对接,节约成本,数据互通。
需注意的是:由于是O2O,同一商品,在不同平台的不同门店,价格可能不同。所以若有n个实体店,m个商品的话,那么在每个平台,商户最多就要维护n*m条数据。
若w个销售渠道(平台),那么最多就要维护n*m*w条数据。这个客观现实就为本次事件埋下伏笔。
02. 核心功能:同步库存、价格给第三方平台
功能基于模型,所以正向功能就是:库存价格变化,则同步到对应的各个平台。
触发条件除了WMS增量自动同步之外,还需要手动触发同步的机制。
比如,美团打折活动结束,就要触发同步WMS的价格进行恢复。若此时不具有触发增量的条件,就需要手动触发。
于是增加了批量、单个的功能。
至此,触发同步的条件就确定了:单个同步、批量同步、增量自动同步。
功能流程如下图:
03. 技术实现机制
总体机制:不同平台的商品,从WMS搜集待同步的数据,然后集中后发车完成同步。
第一期的方案是采用“同步池”,汇集所有的同步请求。即:将来自于WMS的定时增量推送、页面批量操作、单个操作的同步请求数据,集中在同步池中。
再按照各自的去向,寻找对应的平台接口,此时需服从各平台的限流规则。
限流规则:就是平台限制接口被请求的次数。比如美团限制每天只支持10万次的同步请求。
整理后的技术实现流程图:
04. 出现的问题
主要有三个问题表现:同步池中的数据量会很大;经常量丢数据导致同步失败;用户等待时间过长。
1)数量大的原因:
基数大 由于各个平台和门店按照每个商户有200个连锁店,每个商户有2000个商品,那么就又有20万条基础数据。
若同时使用3个平台,最大就有60万基础数据。
触发次数多 假设不同平台和门店在正常销售,那么WMS的库存就会不停变化,于是就会不停地增量推送数据,请求同步到平台。
同时,商户又在单个或批量进行同步。商户为确保万无一失还会选择重复操作同步。
2)丢数据的原因:
三方平台限流,提交过多的数据就被限制不执行。若平台不反馈失败数据,那么失败后我们也不知道遗漏了哪些。 数据量过大,占用线程挤满,资源不够。 3)执行时间太久的原因:
目前平台的限流大致都是100条/秒,一个门店按照2000条商品,最快10秒完成,正常情况下20w商品数据需要近一小时。
总结以上,根源是数据量过大的问题。监控到2天有300w+的同步任务产生。
这就导致请求失败过多,用户继续重新同步,恶性循环,导致同步任务可能会很长一段时间无法降低,任务积压。不丢都难。
05. 优化方案
1)降低批量操作的频次
将同步库存和同步价格按钮分开 最初,同步库存和价格的按钮是在一起的,即。
这就导致每点击一下,就要同时同步库存和价格到三方平台的后台。
而事实上,价格的变更很少见,而库存的同步相对比较频繁(任何一个平台的任何一个门店产生订单,都会引发异动)。
如果不拆开,那么每次的请求都双份的(注:平台接口是支持拆开的)。
限制频繁操作同步按钮 同步库存货价格的按钮点击之后,若上个任务没执行完,则按钮不允许再次操作。
表面上看,若不做限制,貌似让用户随时用着爽,但实际上根本爽不起来。
2)对同步池中的数据进行过滤
只取时间戳最新的执行 根据唯一键,对重复提交进来的数据进行去重。
比如手动点击同步,系统又自动增量同步,那么这两次请求只取最后这次的。
对比上次同步成功的数值,和本次提交的同步数值 如果数值没变化,那么同步过去也是无意义的,可以直接跳过这条任务。
比如上次已经同步过,且成功了,那么这次就算手动触发了同步,一旦对比到当前的价格和上次同步的价格是相同的,那就没必要再次同步了。
3)增加补推机制
在同步给平台失败的场景比较多。
若是数据本身不具备同步的条件,例如缺少默写必须信息。或者不满足平台的约束条件,比如平台无此数据。那么只能返回原因,告诉用户处理后再试。
若是上述两种条件都满足,但是平台因为限流,导致部分数据遗留下来的话,理论上持续补推的话,总会完结的。
但是,考虑到后面还有很多数据在等待,所以这里不能一直补推。
最终的方案就是间隔1s重新插入补推2次。
补推还不成功的,就停止补推,并汇报原因,便用户自己再手动同步。
文章目录 前言一、部署所需二、环境配置三、部署流程1.环境配置2.图形化部署3.数据库初始化 前言 博主全程root用户操作,不是root请加sudo
一、部署所需 1.Oracle 11g R2安装包(百度云,提取码:q61i )
2.java(教程)
二、环境配置 systemctl disable --now firewalld # 防火墙关闭,如果是云服务器安全组记得放行 setenforce 0 # selinux关闭 sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux sed -i 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/selinux/config yum install wget tar vim net-tools curl -y # 常用插件安装 三、部署流程 1.环境配置 安装oracle所需依赖项:
yum -y install binutils* compat-libcap1* compat-libstdc++* gcc* gcc-c++* glibc* glibc-devel* ksh* libaio* libaio-devel* libgcc* libstdc++* libstdc++-devel* libXi* libXtst* make* sysstat* elfutils* unixODBC* 新建组和用户:
groupadd oinstall groupadd dba useradd -g oinstall -g dba -m oracle passwd oracle 新建数据库存放目录:
一.安全距离名词解释:
安全距离包括电气间隙(空间距离),爬电距离(沿面距离)和绝缘穿透距离。
1、 电气间隙:两个导体部件之间的最短空气路径。
2、 爬电距离:沿两个导体部件之间绝缘材料表面的最短路经。
二、绝缘部分名词解释
基本绝缘:用于带电部分上对电击起基本防护作用的绝缘
辅助绝缘:附加于基本绝缘的独立绝缘,当基本绝缘失效时由它来提供对电击的防护
双重绝缘:由基本绝缘和辅助绝缘组成的绝缘
加强绝缘:用于带电部分的单绝缘系统,它对电击的防护程度相当于本标准规定条件下的双重绝缘
如下图:我们常见的人能摸到的导线的外层就可以看做是双重绝缘,即基本绝缘+辅助绝缘=双重绝缘。
要注意的是 基本绝缘可以独立存在,而 辅助绝缘必须是在有基本绝缘的基础上而存在的,换句话说辅助绝缘就是在辅助基本绝缘的一个绝缘。在没有基本绝缘的情况下,独立的绝缘不能叫辅助绝缘。
加强绝缘和双重绝缘的区别:
加强绝缘是单一的绝缘结构,构成绝缘层的绝缘材料不能够拆分成基本绝缘、辅助绝缘等。 加强绝缘例子如:一般电器产品的塑胶外壳。
而双重绝缘是多个绝缘合起来组成的。双重绝缘可以拆分成基本绝缘和附加绝缘,如上述举例。
再拿个生活例子穿衣服来说吧.
基本绝缘:穿了一件衣服
辅助绝缘:可能有点冷,在原来的衣服上再加一件
双重绝缘:两件衣服的统称,即第一件衣服+第二件衣服.
加强绝缘:把第一件衣服脱了换比较厚的保暖衣.还是只有一件衣服,但此件衣服可以是一层也可以是两层或多层.
三、漏电流定义
漏电流为非功能性电流,可分为对地漏电流、外壳漏电流和患者漏电流。
对地漏电流:由网电源部分穿过或跨过绝缘流入保护接地导线的电流。
外壳漏电流:在正常使用时,从操作者或患者可触及的外壳或外壳部件(应用部分除外),经外部导电连接而不是保护接地导线流入大地或外壳其他部分的电流。
患者漏电流:从应用部分经患者流入地的电流,或是由于在患者身上出现一个来自外部电源的非预期电压而从患者经 F 型应用部分流入地的电流。
四:接地
分为功能接地和保护接地
功能接地:
(1)工作接地
为了保证电力系统运行,防止系统振荡.保证继电保护的可靠性,在交直流电力系统的适当地方进行接地,交流一般为中性点,直流一般为中点,在电子设备系统中,则称除电子设备系统以外的交直流接地为功率地。
(3)屏蔽接地
将电气干扰源引入大地,抑制外来电磁干扰对电子设备的影响,也可减少电子设备产生的干扰影响其它电子设备。
(4)信号接地
为保证信号具有稳定的基准电位而设置的接地,例如检测泄漏电流的接地,阻抗测量电桥和电晕放电损耗测量等电气参数测量的接地。
保护接地:
是为防止电气装置的金属外壳、配电装置的构架和线路杆塔等带电危及人身和设备安全而进行的接地。所谓保护接地就是将正常情况下不带电,而在绝缘材料损坏后或其他情况下可能带电的电器金属部分(即与带电部分相绝缘的金属结构部分)用导线与接地体可靠连接起来的一种保护接线方式。接地保护一般用于配电变压器中性点不直接接地(三相三线制)的供电系统中,用以保证当电气设备因绝缘损坏而漏电时产生的对地电压不超过安全范围。
五、导线绝缘的颜色
保护接地导线的整个长度都应以 绿/黄色的绝缘为识别标志。
C语言里宏没有过时,在一些著名库或者底层源码中,它们的身影无处不在。虽然宏有很多陷阱(以至于有些编码规范中要求“尽量少用宏”),针对“宏”的缺陷,C++发明出template(模板),inline function(内联函数),constexpr(常量表达式)等等瑞士军刀工具(针对某种场景的专用工具)。在有些场合“宏”是无可替代的必需品。标识符拼接生成,或者字符串拼接自动生成领域,宏不可替代。因为模板只能繁殖一些类型,无法繁殖标识符或者字符串。在真正用好宏这个工具前,需要理解一下知识点。
宏拒绝递归(Self-Referential) 函数是可以递归的,自己调用自己。宏却不可以递归,因为宏是没有办法定义终止递归的条件。例如:#define A (A+10)这个宏,假设递归下去,就是A => (A+10) => ((A+10)+10) => (((A+10)+10)+10) .... 直到内存耗尽,根本停不下来。
那么#define A (A+10)就是非法的宏了?不是的,这个宏是合法的,A就会直接被替换为A+10,宏替换结束,代码被扔给编译器(之前是预处理器做宏替换)。编译器如何理解A+10?假设恰好有个变量叫做A,则编译通过;假设找不到A这个标识符,则编译报错。
自引用(Self-Referential)是终止宏向更深层替换的一个条件(另外还有#,##也会终止宏向更深处滑落)。分析下面这个例子,可以更深刻的理解自引用以及“间接自引用”的问题:
#define A(x,y) B(x,y) @@@ C(x,y) #define B(x,y) D(x,y) @@ E(x,y) #define C(x,y) F(x,y) @@ G(x,y) #define D(x,y) x+y #define E(x,y) x-y #define F(x,y) x*y #define G(x,y) A(x,y) $ B(x,y) // A(1,2) 这个宏展开的结果是:1+2 @@ 1-2 @@@ 1*2 @@ A(1,2) $ 1+2 @@ 1-2 下图为语法树的样子。当A(1,2)层层展开,遇到G这个宏时,G的宏定义里有个A,A是直系祖先,应停止展开A(1,2)。当G这个宏遇到B(1,2)时,B不是直系祖先,所以展开了B。
预处理器内部应该能记忆这个“家谱”
宏的PreScan 宏是允许有参数,宏的实参也允许是一个宏。问题来了,函数的实参是先求值,然后再传入函数的。宏的实参是先展开再传入宏体的?还是不展开实参,先带入宏体,再展开呢?先举一个例子:
#define min(x,y) ( (x)<(y) ? (x) : (y) ) int main() { std::cout << min(min(1,2) ,3) ; } 首先,这条语句是合法合理的,cout输出1,符合预期。然后,假设它是先把min(1,2)带入宏体的,则第一次展开为(min(1,2)>3?
产品经理的职责是什么 首先,在不同类型的公司产品经理的职责往往不一样。
在交易驱动的公司(就是围绕交易订单的,如新零售、电商、O2O)中,产品经理实际上是PD的角色,即产品设计师,需要配合运营的需求,话语权较低,这时候主要负责的是系统设计方面。
在用户驱动的公司(以用户为核心,如短视频、工具应用、社交)中,在前期产品驱动的时期,产品经理是业绩指标的背负者,这时候的产品经理则是PM的角色,他既要考虑商业模式,又要联动运营,还要负责系统的设计,这时候的产品经理需要三点协同。
第二点,在公司的不同时期产品经理的职责也不一样。
初创公司
独角兽公司
巨头公司
特点
船小好掉头
业务模型成熟且快速发展
资源强大、各个部门分工明确
创新性
大规模创新
微创新(大规模的创新基本停止)
创新来自于高层(求稳,害怕创新带来的风险)
产品经理话语权
能够左右运营
被运营的需求左右
负责具体的需求落地工作
第三,在产品的不同生命周期(需求、设计、开发、测试、发布、迭代)中,产品经理的职责也各有不同。
在产品的定义阶段,产品经理需要做市场调研、用户分析、竞品分析、盈利分析、撰写需求文档等工作,这时期产品经理的职责是明确产品的目标用户群与特征(用户画像),获取、评估用户需求。
在产品的设计阶段,产品经理需要设计产品的功能列表、业务流程、用户用例、信息架构、界面布局等。
在产品的开发阶段,产品经理主要把控需求管理(主要是尽量不要更改需求)、管理开发进度
在测试阶段,产品经理主要负责可用性测试、用户体验测试等,即需求验收。
在发布阶段,产品经理负责用户教育(让用户为产品的更新做准备)、销售培训、推广方案确定、运营策略等
在迭代阶段,产品经理主要进行数据分析、分析用户反馈、功能改进等。
总结产品经理的职责:
1.明确产品的目标用户,获取管理用户需求,代表用户说话,撰写需求文档;
2. 设计产品原型、业务流程、信息架构等;
3. 项目管理、需要管理、需求验收;
4. 产品运营数据分析。
使用Python写简单的脚本已经有几个月了,由于不是经常写,导致每次用起来经常会忘记一些写法,现在做个笔记:
分类方法、函数作用操作系统
os.name查看操作系统类型
os.uname()函数操作系统详细信息环境变量
os.environ环境变量
os.environ.get('key')某个环境变量的值操作文件、目录
os.getcwd()获取当前目录
os.listdir( )目录列表
os.mkdir()创建文件、目录
os.rmdir()删除文件、目录
os.chdir()改变默认目录
shutil.copyfile()复制文件文件重命名、删除
os.rename()文件重命名
os.remove()文件删除
os.path模块
os.path.abspath()绝对路径
os.path.join()重组路径
os.path下拆分路径
os.path.split()拆分路径
os.path.splitext()拆分路径的扩展名
os.path下判断函数
os.path.isdir()判断目录
os.path.isfile()判断文件
#大括号转义
使用两个{{ 或 }},而不是使用\{ 或 \}
1、时间戳
import datetime(自带库)
print "# time is :", datetime.datetime.now().strftime('%Y-%m-%d%H:%M:%S')
时间格式转换,比如(10/01/2019 --> 2019-10-01)
systemInfoList = cpuResultList[0].split()
timeArray = time.strptime(systemInfoList[3], "%m/%d/%Y")
saTime=time.strftime("%Y-%m-%d", timeArray)
时间戳-->时间格式转换
saTmpFileAdjustTimeStamp = os.path.getmtime(saTmpFile)
timestampTmp = time.localtime(saTmpFileAdjustTimeStamp)
saTmpFileAdjustTime = time.strftime('%Y-%m-%d', timestampTmp)
2、打开文件使用with写法,防止忘记关闭文件句柄。
with open('project.lib') as pr:
for line in pr:
今日对红外避障小车软件部分进行了调试:
这里主要是编写L298N有关代码实现对小车两电机的控制,其逻辑功能如下
写好代码后我将程序烧录进单片机运行小车,发现同一代码下两电机运行方向相反,我将电平赋值对调才能使两电机同向转动,最终代码如下:
#include <REG52.H> sbit ENA=P2^2; sbit IN1=P2^1; sbit IN2=P2^0; sbit ENB=P0^0; sbit IN3=P0^1; sbit IN4=P0^2; sbit A1=P1^0; sbit B2=P1^1; void delay(int z) { int x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void back() { ENA=1; IN1=1; IN2=0; ENB=1; IN3=0; IN4=1; } void go() { ENA=1; IN1=0; IN2=1; ENB=1; IN3=1; IN4=0; } void left() { ENA=1; IN1=1; IN2=0; ENB=1; IN3=1; IN4=0; } void right() { ENA=1; IN1=0; IN2=1; ENB=1; IN3=0; IN4=1; } void main() { while(1) { go(); if(B2==0) { back(); delay(500); left(); delay(700); } if(A1==0) { back(); delay(500); right(); delay(700); } } } io口定义部分我根据自己接线的实际情况进行了调整。
== 用于比较两者是否相等,忽略数据类型。
=== 用于更严谨的比较,值和值的数据类型都需要同时比较
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <script src="vue.js" type="text/javascript" charset="utf-8"></script> <body> <div id="app"> <div v-if="text ==1 "> 1--值一样,类型不同,两个等号显示 </div> <div v-if="text ===1 "> 2--值一样,类型不同,三个等号不显示 </div> <div v-if="text ==='1' "> 3--值一样,类型同,三个等号显示 </div> </div> <script type="text/javascript"> /* text:"1" 这里的1是个字符串 */ var vm = new Vue({ el:"#app", data:{ text:"1" } }); </script> </body> </html> 结果:
如果我试图创建一个虚拟环境,我会得到这个错误消息,我不明白这一点:错误的解释器:没有这样的文件或目录。我已经回顾了this stack overflow answer,并尝试在下面的诊断步骤中应用它。在
这是我第一天在莫哈韦跑步,但我不知道这是否是这个问题的一个因素。在
我在/Users/Wes/Dropbox/Programming/Python/glade_againn为项目创建了一个新的空文件夹
我的计划是在virtualenv中运行这个项目/Users/Wes/.virtualenvs/glade_againn
但是,当我尝试使用virtualenv时,我得到了这个错误消息。在$ virtualenv --version
-bash: /usr/local/bin/virtualenv: /usr/local/opt/python/bin/python2.7: bad interpreter: No such file or directory
如果我试图用PIP安装virtualenv,我会被告知它已经存在。在
^{pr2}$
我现在的道路是echo $PATH
/Library/Frameworks/Python.framework/Versions/3.6/bin:/opt/local/bin:/opt/local/sbin:/usr/local/opt/postgresql@9.4/bin:/usr/local/Cellar/postgresql/9.5.4_1/bin/psql/:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Applications/Wireshark.app/Contents/MacOS:/usr/local/git/bin:/Users/Wes/bin:/sw/bin:/usr/local/bin:/Users/Wes/.sdkman/candidates/groovy/current/bin/
如果你在所有这些目录中搜索pyth*,就会得到这个列表,顺序如下。在/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3-config
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6-config
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6m
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6m-config
/opt/local/bin/python2.7
/opt/local/bin/python2.7-config
/opt/local/bin/python3.4
/opt/local/bin/python3.4-config
/opt/local/bin/python3.4m
/opt/local/bin/python3.4m-config
/opt/local/bin/pythonw2.7
/usr/local/bin/python-32
/usr/local/bin/python2-32
/usr/local/bin/python2.7-32
/usr/local/bin/python3
/usr/local/bin/python3-config
/usr/local/bin/python3.6
/usr/local/bin/python3.6-config
/usr/local/bin/python3.6m
/usr/local/bin/python3.6m-config
/usr/local/bin/pythoni
/usr/local/bin/pythoni1
/usr/local/bin/pythonw-32
/usr/local/bin/pythonw2-32
/usr/local/bin/pythonw2.7-32
/usr/bin/python
/usr/bin/python-config
/usr/bin/python2.7
/usr/bin/python2.7-config
/usr/bin/pythonw
/usr/bin/pythonw2.7
/sw/bin/python2.7
/sw/bin/python2.7-config
/usr/local/bin/python-32
/usr/local/bin/python2-32
/usr/local/bin/python2.7-32
/usr/local/bin/python3
/usr/local/bin/python3-config
/usr/local/bin/python3.6
/usr/local/bin/python3.6-config
/usr/local/bin/python3.6m
/usr/local/bin/python3.6m-config
mysql是现在普遍使用的数据库,但是如果宕机了必然会造成数据丢失。为了保证mysql数据库的可靠性。就要会一些提高可靠性的技术。
主从复制原理如下。
slave(从服务器)
master(主服务器)
mysql主从是异步复制过程
master开启bin-log功能,日志文件用于记录数据库的读写增删
需要开启3个线程,master IO线程,slave开启 IO线程 SQL线程,
Slave 通过IO线程连接master,并且请求某个bin-log,position之后的内容。
MASTER服务器收到slave IO线程发来的日志请求信息,io线程去将bin-log内容,position返回给slave IO线程。
slave服务器收到bin-log日志内容,将bin-log日志内容写入relay-log中继日志,创建一个master.info的文件,该文件记录了master ip 用户名 密码 master bin-log名称,bin-log position。
slave端开启SQL线程,实时监控relay-log日志内容是否有更新,解析文件中的SQL语句,在slave数据库中去执行。
字有点多 上张图看看。
应该有一定了解了吧。、
准备两个mysql,一个做主,一个做从。防火墙,selinux都要关闭,保证可以ping通对方
主服务器配置: vi/etc/ntp.conf
添加:
server 127.127.1.0
fudge 127.127.1.0 stratum 8
service ntpd start #因为同步数据 两个服务器的时间也要同步。
稍后要在从服务器执行来同步时间
vi/etc/my.cnf 在配置文件49行
其他内容都可以保持默认。
---------------------------------------------------------------------------------------------------------
在主服务器登录mysql 给从服务器授权。
mysql> grant replication slave on *.* to zs@'192.168.43.%' identified by '123456';
授权用户zs 密码为123456 允许192.168.43.0的网络连接 一会儿要在slave上使用这个账号
----------------------------------------------------------------------------------------
show master status; #此命令查看主服务器的bin-log日志文件名称和position点
从服务器就是要指定这个文件maste-bin.000001 (随着mysql增删修改日志文件名字也有可能改变) 和 107 (position点 主服务器增删修改都会改变)所以现在开始就不要再在主服务器创表干啥的了,
mysql架构 1)连接层
最上层的连接池是一些连接服务,包含本地sock通信和大多数基于C/S工具实现的类似于TCP/IP的通信。主要完成一些类似于连接处理、授权认证及相关的安全方案。在该层上引入了线程池的概念,为通过认证安全接入的客户端提供线程。同样在该层上可以实现基于SSL的安全连接。服务器也会为安全接入的每个客户端验证它所具有的操作权限。 2)服务层
第二层架构主要完成大多数的核心服务功能,如SQL接口、缓存的查询、SQL的分析和优化、内置函数等。所有跨存储引擎的功能也在这一层实现,如过程、函数等。在该层,服务器会解析查询并创建相应的内部解析树,并对其完成相应的优化如确定查询表的顺序,是否利用索引等,最后生成相应的执行操作。如果是select语句,服务器还会查询内部的缓存,如果缓存空间足够大,这样在频繁读操作的环境中能够很好的提升系统的性能。 3)引擎层
存储引擎真正的负责MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信,不同的存储引擎具有的特性不同,我们可以根据实际需进行选取。下文将对相关存储引擎进行具体介绍。 4)存储层
数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。 SQL的执行过程:数据库通常不会被单独使用,而是由其它编程语言通过SQL支持接口调用MySQL,由MySQL处理并返回执行结果。首先,其它编程语言通过SQL支持接口调用MySQL,MySQL收到请求后,会将该请求暂时放在连接池,并由管理服务与工具进行管理。当该请求从等待队列进入到处理队列时,管理器会将该请求传给SQL接口,SQL接口接收到请求后,它会将请求进行hash处理并与缓存中的数据进行对比,如果匹配则通过缓存直接返回处理结果;否则,去文件系统查询:由SQL接口传给后面的解析器,解析器会判断SQL语句是否正确,若正确则将其转化为数据结构。解析器处理完毕后,便将处理后的请求传给优化器控制器,它会产生多种执行计划,最终数据库会选择最优的方案去执行。确定最优执行计划后,SQL语句交由存储引擎处理,存储引擎将会到文件系统中取得相应的数据,并原路返回。
缓存 mysql 缓存机制简单来说就是缓存sql文本以及查询结果,如果运行相同的sql,服务器直接从缓存中取到结果,不需要再去解析和执行sql.
通过设置query_cache_type来控制缓存的开关 0off 1on 2 demand
select SQL_NO_CACHE * from my_table where ...
select SQL_CACHE * from my_table where ...
引擎 Innodb 支持事务,最小锁粒度是行锁,更适合写,但是目前已经优化的足够好,读取能力不弱于myisam
支持外键
聚簇索引,聚簇索引的文件存放在主键索引的叶子节点,索引innodb必须要有主键
Myisam 不支持事务,最小锁粒度是表锁,更适合查询
不支持外键
非聚簇索引
MyIsam的优势可能就剩下占用空间更小吧
锁 表级锁:开销小,加锁快;不会出现死锁;锁粒度大,发生锁冲突的概率最高,并发度最低。
页面锁:开销和加锁时间介于表锁与行锁之间;会出现死锁;锁粒度处于表锁与行锁之间;
行级锁:开销大,加锁慢;会出现死锁;锁粒度最小,发生锁冲突的概率最低,并发度也最高;
乐观锁:用一个数据版本(version)记录来实现;每次在更新之前先查到版本号,再根据版本号去更新,保证了这条数据在同一时刻只能被一个事务修改。乐观锁是我们用代码实现的一种加锁方式;
悲观锁:悲观锁就是在操作数据时,认为此操作会出现数据冲突,所以在进行每次操作时需要先通过获取锁才能对相同的数据进行修改。悲观锁时数据库自己实现的,共享锁和排他锁都属于悲观锁
共享锁:读锁S锁;其他事务只能加S锁;其他事务只能访问该资源不能进行修改必须等到该资源的所有锁被释放;
排他锁:写锁X锁;其他事务不能加任何锁;且不能访问该资源;必须等X锁释放
如果加排他锁可以使用select ...for update 语句,加共享锁可以使用select ... lock in share mode语句。所以加过排他锁的数据行在其他事务种是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select ...from...查询数据,因为普通查询没有任何锁机制。
行锁
行锁:多个事务操作同一行数据时,后来的事务处于阻塞状态;innodb只有在通过索引条件检索数据时使用行级锁,否则使用表锁
innodb的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁
劣势:开销大,加锁慢,会出现死锁
优势:锁粒度小,发生锁冲突的概率低,处理并发能力强
首先创建好对应的微服务,至少两个服务以上
新版本的 RunDash 被 Services 所替代
点击加号
选择 Application
重新启动项目即可
1xx(临时响应) 100: 请求者应当继续提出请求。
101(切换协议) 请求者已要求服务器切换协议,服务器已确认并准备进行切换。
2xx(成功) 200:正确的请求返回正确的结果
201:表示资源被正确的创建。比如说,我们 POST 用户名、密码正确创建了一个用户就可以返回 201。
202:请求是正确的,但是结果正在处理中,这时候客户端可以通过轮询等机制继续请求。
3xx(已重定向) 300:请求成功,但结果有多种选择。
301:请求成功,但是资源被永久转移。
303:使用 GET 来访问新的地址来获取资源。
304:请求的资源并没有被修改过
4xx(请求错误) 400:请求出现错误,比如请求头不对等。
401:没有提供认证信息。请求的时候没有带上 Token 等。
402:为以后需要所保留的状态码。
403:请求的资源不允许访问。就是说没有权限。
404:请求的内容不存在。
5xx(服务器错误) 500:服务器错误。
501:请求还没有被实现。
##onstat -d 查看数据库表空间信息
onstat -d命令用于检查数据库空间的使用情况
[gbasedbt@node13 ~]$ onstat -d Your evaluation license will expire on 2021-08-27 00:00:00 GBase Database Server Version 12.10.FC4G1TL -- On-Line (Prim) -- Up 00:16:02 -- 2023104 Kbytes Dbspaces address number flags fchunk nchunks pgsize flags owner name 55143028 1 0x60001 1 1 2048 N BA gbasedbt rootdbs 576e8028 2 0x40001 2 1 2048 N BA gbasedbt plogdbs 576e8258 3 0x60001 3 1 2048 N BA gbasedbt llogdbs 576e8488 4 0x42001 4 1 8192 N TBA gbasedbt tmpdbs1 576e86b8 5 0x40001 5 1 16384 N BA gbasedbt datadbs1 576e88e8 6 0x48001 6 1 2048 N SBA gbasedbt sbspace1 576e8b18 7 0x40001 7 1 16384 N BA gbasedbt datadbs2 7 active, 2047 maximum Chunks address chunk/dbs offset size free bpages flags pathname 55143258 1 1 0 102400 75469 PO-B-D /home/gbasedbt/gbs_server/data/storage_hdr5/rootdbs 5770b028 2 2 0 500000 4947 PO-B-D /home/gbasedbt/gbs_server/data/storage_hdr5/plogdbs 5770c028 3 3 0 5500000 4899947 PO-BED /home/gbasedbt/gbs_server/data/storage_hdr5/llogdbs 5770d028 4 4 0 125000 124947 PO-B-- /home/gbasedbt/gbs_server/data/storage_hdr5/tmpdbs1 5770e028 5 5 0 125000 64642 PO-BED /home/gbasedbt/gbs_server/data/storage_hdr5/datadbs1 57b02028 6 6 0 500000 466272 466272 POSB-D /home/gbasedbt/gbs_server/data/storage_hdr5/sbspace1 Metadata 33675 25057 33675 57b03028 7 7 0 625000 389399 PO-B-D /home/gbasedbt/gbs_server/data/storage_hdr5/datadbs2 7 active, 32766 maximum NOTE: The values in the "
内容提要:
1 极小集; 2 极限点; 3 关于稠密性的结论补充; 本文主要参考文献. 本文的前置内容为:
格罗卜学数学:拓扑动力系统(1): 基本概念, Li-Yorke定理和Sharkovskii定理
本文之后请继续食用:
格罗卜学数学:拓扑动力系统(4): 拓扑熵
更多内容,请移步专栏目录:
格罗卜:格罗卜的数学乐园-目录zhuanlan.zhihu.com 设 是一个 紧致Hausdorff空间, 是 连续映射, 上的连续自映射序列 称作 上由连续自映射 经迭代而生成的 紧致拓扑离散半动力系统 , 简称 紧致系统, 记为 . 1 极小集, Birkhoff定理
1-1. [极小集] 称 是极小集. 如果满足如下等价条件之一: (1) 不包含任何真不变闭子集; (2) , , 即 中每一点的轨道都在 中稠密; (3) 对于每个非空开集 , 存在有限子集 , 使得 . [证明] (1) (2) 显然. (1) (3) 设 . 那么 为闭不变的. 根据假设 . 根据 的紧致性,就有(3)成立. (3) (1) 设 为非空闭不变的.
该错误TypeError: 'str' object is not callable字面上意思:就是str不可以被系统调用,
其实原因就是:你正在调用一个不能被调用的变量或对象,具体表现就是你调用函数、变量的方式错误.
所以,这个错误想表达的就是:str()是系统自带的,你不能在用它的时候自己同时定义一个别的叫做str的变量,这样会冲突.
出现这个情况错误一般是
1、str变量重复定义
2、变量重复定义
3、函数或者字符串调用错误
例子1:str字符串重复定义
classmate = ['one', 'two', 'three']
for str in classmate:
print(s + ', ')
print('\n')
str() 是一个builtin 函数,在这里将一个普通变量定义为str,编译器在之后的解释执行过程中,会一直把str作为一个普通变量处理,自然在希望调用str()的时候会出问题。
把这里的 str 改成 s 等其他变量,就能解决问题。
例子2、变量名重复定义
class Book:
def __init__(self, price, color):
self.price = price
self.color = color # color发生冲突,导致出错
def color(self):
print('书的颜色是:%s'%self.color)
eng = Book(10, 100, 'red')
print('书的价格是:%d'%eng.price)
eng.color()
Traceback (most recent call last):
File "/home/albert/PycharmProjects/xi.py", line 14, in eng.
有些用户用了几年的笔记本电脑,觉得内存不够,想自己加内存条,但是对于电脑的操作不是那么熟悉,不敢随意拆卸。那么这篇文章就是系统部落给大家带来的笔记本增加内存条图文教程。
大家在选购内存条的时候,还需要注意选择笔记本内存条,笔记本最大支持内存是多少,类型是DDR3的还是DDR4的,内存条频率等;
图文教程:
1、给笔记本安装内存条之前,翻转笔记本将电池卸下,拆卸方法:在背面将右边电池锁开关打开,左边的电池锁往左推(保持不动),然后将电池卸下;
2、电池拆卸下来后,使用螺丝刀,拧下笔记本背后T型区域的螺丝,然后打开后盖;
3、打开笔记本后盖,T型区域左上角就是添加内存条的地方;
4、插入内存条的时候需要注意:首先要确定内存条的正反面,在内存条上有一个小口(缺口),只需将此小口与内存条插座上凸起来的地方对齐即可;
5、小口与凸起的地方对齐后,即可将内存条插进去,这个时候,会发现内存条是翘起来的,然后将内存条按下两边的固定开关,扣紧。如果以后想要取下内存条,只需要将固定开关,向外拨开即可轻松取下内存条;
6、内存条安装完成后,将笔记本电脑后壳盖上,拧上螺丝和装上电池,添加内存条的任务就完成了;
注意:由于市面上每款笔记本的设计,内存条位置不一样,所以需要大家根据实际的情况进行操作,但是大多数情况下,都是大同小异的,装卸的难度并不算高。
以上就是笔记本内存条安装步骤|笔记本内存条安装图解文章,如有其他电脑问题,或者要想了解更多技术教程,请继续关注系统部落。
大家经常可以听到二层网络、三层网络的说法,我们这里提到的二层、三层是按照逻辑拓扑结构进行的分类,并不是ISO七层模型中的数据链路层和网络层,而是指核心层、汇聚层和接入层。这三层都部署的就是三层网络结构,二层网络结构没有汇聚层。那么,二层网络和三层网络有什么区别呢?接下来就由飞畅科技的小编带大家一起来看看二层网络和三层网络的区别。
1. 二层网络
只有核心层和接入层的二层网络结构模式运行简便,交换机根据MAC地址表进行数据包的转发。
有则转发,无则泛洪,即将数据包广播发送到所有端口,如果目的终端收到给出回应,那么交换机就可以将该MAC地址添加到地址表中,这是交换机对MAC地址进行建立的过程。
但这样频繁的对未知的MAC目标的数据包进行广播,在大规模的网络架构中形成的网络风暴是非常庞大的,这也很大程度上限制了二层网络规模的扩大,因此二层网络的组网能力非常有限,所以一般只是用来搭建小局域网。
2. 三层网络
与二层网络不同的是,三层网络结构可以组件大型的网络。
核心层是整个网络的支撑脊梁和数据传输通道,重要性不言而喻。
因此在整个三层网络结构中,核心层的设备要求是最高的,必须配备高性能的数据冗余转接设备和防止负载过剩的均衡负载的设备,以降低各核心层交换机所承载的数据量。
汇聚层是连接网络的核心层和各个接入层的应用层,在两层之间承担“媒介传输”的作用。
汇聚层应该具备以下功能:实施安全功能(划分VLAN和配置ACL)、工作组整体接入功能、虚拟网络过滤功能。因此,汇聚层交换机设备应采用三层交换机。
接入层的面向对象是终端客户,为终端客户提供接入功能。
二层网络仅仅通过MAC寻址即可实现通讯 ,但仅仅是同一个冲突域内;三层网络则需要通过IP路由实现跨网段的通讯,可以跨多个冲突域。
三层交换机在一定程度上可以替代路由器,但是应该清醒地认识到三层交换机出现最重要的目的是加快大型局域网内部的数据交换。
它所具备的路由功能也多是围绕这一目的而展开的,所以他的路由功能没有同一档次的专业路由器强,在安全、协议支持等方面还有很多欠缺,并不能完全取代路由器工作。
在实际应用过程中,典型的做法是:处于同一个局域网中的各个子网的互联以及局域网中VLAN间的路由,用三层交换机来代替路由器,而只有局域网与公网互联之间要实现跨地域的网络访问时,才通过专业路由器。
好了,以上内容就是飞畅科技关于二层网络和三层网络区别的相关详细介绍,希望能对大家有所帮助!飞畅科技20年专业从事光端机、工业级交换机、光纤收发器、协议转换器等工业通信设备的研发、生产和销售,欢迎前来了解、交流。
我们在使用浏览器浏览网页时,有时候会因为不明原因导致页面被劫持,也就是跳转到其它页面,让你无法正常浏览想要看的内容,这个通常是一些软件在安装的时候修改了注册表导致,而小编这里本次就跟大家分享一下Windows7网页被劫持的解决方法。
详细如下
1、同时按下“win+R”键打开运行窗口;
2、在运行窗口内输入“regedit”点击确认进入注册表页面;
3、打开注册表编辑器之后,左边的树形路径中找到下面两个注册表项目,在StartPage上按两下并删除方框中的数值。
4、完成后IE的首页就不会再被其他的网页占据了,不过如果你修改完重开机之后问题还在的话,打开运行,在运行输入框中输入msconfig,然后点击确定。
5、在启动分页中找找看有没什么不是你要的、不认识的软件或程序,如果你不希望哪个程序在开机时自动启动的话,可以取消左边的勾,重启电脑就可以了。
以上就是Windows7网页被劫持的详细解决方法,希望可以帮助到你。
ROS:机器人软件平台(一) 导论
ROS简介
“ROS是一个开放源代码的机器人元操作系统。它提供了我们对操作系统期望的服务,包括硬件抽象、低级设备控制、常用功能的实现、进程之间的消息传递以及功能包管理。它还提供了用于在多台计算机之间获取、构建、编写和运行代码的工具和库。”
换句话说,ROS包括一个类似于操作系统的硬件抽象,但它不是一个传统的操作系统,它具有可用于异构硬件的特性。此外,它是一个机器人软件平台,提供了专门为机器人开发应用程序的各种开发环境。
我们为什么要学习ROS这个新的概念?这是在线下的ROS研讨会中经常听到的用户们的提问。片面来讲是为了缩短开发时间。我们常说为了学习新的概念所花费的时间太可惜了,因为要修改已经建立好的系统和现有的程序,所以想维持现有的方式。但ROS不需要完全重新开发已有的系统和程序,而是通过加入一些标准化的代码就能对已有的非ROS程序进行ROS化的转化。并且很多通用的工具和软件都有提供,因此可以专注于自己感兴趣或想贡献的部分,这反而可以节省开发和维护所需的时间。让我们来了解一下这种方式的五种特点吧。
第一, 程序的可重用性。 专注于自己想要开发的部分,对剩下的功能可以下载相关功能包来使用。相反,也可以将自己开发出来的程序和其他人分享,让他们也可以使用。比如,美国的NASA为了控制宇宙空间站里使用的Robonaout29机器人,除了使用自行开发的程序,还结合了可以在多种操作系统使用的ROS和具有实时控制、消息通信修复、可靠性等特点的OROCOS,得以在宇宙中执行任务。前面介绍的Robotbase公司的例子也是充分发挥可重用性的案例。
第二, 是基于通信的程序。 为了提供一种服务,很多时候在同一个框架里编写很多程序:从传感器或舵机的硬件驱动到传感、识别和动作等所有种类的程序。但为了重用机器人软件,根据每个处理器的用途将其分成更小的部分。根据平台的不同,我们将此称为组件化或节点化。必须由划分为最小执行单元的节点之间发送和接收数据,而平台具有关于该数据通信的所有一般信息。而且,这与最小的单位进程连接到网络的物联网(IoT)的概念一致,因此可以用作物联网平台。并且,被划分成最小执行单元的程序可以进行小单元的调试,这非常有助于找出错误。
第三, 提供开发工具。ROS提供调试相关的工具-2维绘图和3维视觉化工具RViz,所以无需亲手准备机器人开发所需的开发工具,可以直接拿来使用。例如,在机器人开发中,可视化机器人的模型的情况比较多,通过遵守规定的信息格式,可以直接确认机器人的模型,并且还提供3D仿真器,因此易于扩展到仿真实验。另外,最近比较受人关注的点云(point cloud)形式也可以从英特尔RealSense或微软的Kinect获得的3D距离信息转化过来。此外,实验中使用的数据可以被记录下来,因此需要的时候随时都可以重现实验当时的情况。像这样,ROS的一个重要特点是通过为机器人开发提供必要的软件工具,使开发的便利性达到最大化。
第四, 活跃的开发者社区。至今比较封闭的机器人学界和机器人业界都因为前述的功能而走向重视互相之间的合作的方向。其目的可能各自相异,但实际的合作正在通过这种软件平台发生着。其核心是开源软件平台的社区。例如,以ROS为例,到2017年自愿开发和共享的功能包数量超过了5,000个,而解释如何使用它的wiki页面超过1.7万个,这些都由用户个别参与。 而在社区中非常重要的问题和答案已有超过24,000个,用户们通过这些建立着互惠互利的开发者社区。讨论超越了单纯的对于用法的议题,人们在寻找机器人工程软件的必要因素,并摸索出规则。
第五, 生态系统的形成。前面提到的智能手机平台革命是由Android和iOS等软件平台创造的生态系统造成的。这一趋势在机器人领域延续着。起初,各种硬件技术泛滥,却没有能整合它们的操作系统。在这种情况下,如上所述,各种软件平台已经出现,最受瞩目的ROS现在已经开始构建生态系统。这个正在形成的生态系统里,机器人硬件领域的开发者、ROS开发运营团队、应用软件开发者以及用户也能像机器人公司和传感器公司一样从中受益。起步虽然微不足道,但考虑到逐渐增多的用户数量和机器人公司,以及急剧增加的相关工具和库,我期待在不久的将来将会形成一个圆满的生态系统。
ROS是Robot Operating System的缩写,因此会认为是一种操作系统。尤其是那些对ROS不熟悉的人会认为ROS和上面提到的操作系统一样。当我第一次遇到它时,我也认为ROS是一个新的机器人操作系统。
然而更确切地说,ROS是一个元操作系统(Meta-Operating System)。元操作系统不是一个明确定义的术语,而是一个利用应用程序和分布式计算资源之间的虚拟化层来运用分布式计算资源来执行调度、加载、监视、错误处理等任务的系统。
ROS不是传统的操作系统,如Windows、Linux和Android,反而是在利用现有的操作系统。使用ROS前需要先安装诸如Ubuntu的Linux发行版操作系统,之后再安装ROS,以使用进程管理系统、文件系统、用户界面、程序实用程序(编译器、线程模型等)。此外,它还以库的形式提供了机器人应用程序所需的多数不同类型的硬件之间的数据传输/接收、调度和错误处理等功能。这个概念也被称为中间件(Middleware)或软件框架(Software framework)。
ROS开发、管理和提供基于元操作系统的各种用途的应用功能包,并拥有一个负责分享用户所开发的功能包的生态系统(Ecosystem)。如图2-1所示。ROS是在使用现有的传统操作系统的同时,通过使用硬件抽象概念来控制机器人应用程序所必需的机器人和传感器,同时也是开发用户的机器人应用程序的支持系统。
ROS数据通信可以在一个操作系统中进行,但也适用于使用多种硬件的机器人开发,因为可以在不同的操作系统、硬件和程序之间交换数据。
ROS具有以下特征:
【前言】
昨天(2020.12.6)学习期间,突然有篇非常好看的博文映入我的眼帘,说好看,其实是主题好看,当然内容也很优秀。于是乎,我眼馋了,想把自己的博客主题也搞成那个样子,咨询了一下博主大大。他给了我一个链接,真的很优秀,搞了一天(2020.12.7),把自己的博客园也搞成了很漂亮的样子,嘿嘿嘿~
ps:个人觉得博客园和CSDN都各有优势,我习惯用CSDN编辑(因为CSDN可以实时预览),博客园可以上大图(CSDN5M,博客园10M)。博客园我是今年五月份才开了个号,其实没咋玩过,就是有几次CSDN吃了我几个图,我才将几篇博文又贴到了博客园中,以后可以这样:CSDN编辑文本,图片先不慌上传,文本编辑好之后,贴到博客园中,上传图片,再贴回来,集两者之所长!!
文章目录 1、效果2、配置步骤3、我的备份1 CSS2 侧边栏公告3 页脚 1、效果 先上几个图:
博主大大(@氷泠)的链接:https://www.cnblogs.com/6b7b5fc3/p/12729633.html
原始作者(@BNDong)的Git:https://github.com/BNDong/Cnblogs-Theme-SimpleMemory
氷泠大大是站在原始作者的肩膀上眺望远方;
我是站在氷泠大大的肩膀上眺望远方;
而各位可以站在我的肩膀上眺望远方,hhh
2、配置步骤 刚开始我瞎搞一气,原因可能是觉得很难,自己之前没接触过,其实现在回过头来看,操作真的很简单。想要快速上手的话,可以按照如下步骤进行。
St1:登录博客园之后,新开个页面,将https://i.cnblogs.com/settings复制进去,回车(博客园的设置页面)St2:博客侧边栏公告处申请JS权限(理由随便写,比如:写文章需要,装逼需要,开个玩笑。)这步得等一会,然后博客园会给你来个邮件,恭喜你…St3:下载氷泠大大的 Git 源码 (其文尾也有)St4:还是博客园设置页面,皮肤改成SimpleMemory,将下载的css.css文件中的内容贴到页面定制 CSS 代码处(这块啥也不用改),注意禁用模板默认CSSSt5:将下载的side.html文件中的内容贴到博客侧边栏公告处(这块直接贴不能用,得根据自己需要改改,其实就整几个图片得url,音乐的ID即可)St6:将下载的footer.html文件中的内容贴到页脚 HTML 代码处(这块啥也不用改)St7:认真阅读氷泠大大的博文(或side.html文件里面的注释),根据自己需求个性化。St8:保存,大功告成!!! ps:这里用的是原始作者发布的 V1.2.9 版本的,目前(2020.12.7)已经发布了V1.3.3 版本,想要用最新版的,得多花点时间去读html(作为一个小白,我觉得我们只需要在博客侧边栏公告这块改就行)看看咋改的,我嫌太麻烦,就没认真读,现在我是不会 orz
其实整个操作下来要不了多长时间,我就是选图片的时候太挑了(选择恐惧症患者,了解一下),这里提供几个也许会用的到的网站:网易云音乐、路过图床、iconfont(图标)、wallhaven(找图)
3、我的备份 下面贴一下我的设置,做个备份,万一哪天我瞎搞给搞没了,还可以回来。各位也可以先用我的看看效果,但是不可以跟我用的图片一样哦~ QAQ 不然我的主题就不能保持唯一性了 orz
1 CSS *,.Cal{padding:0}body,html{max-height:100%}#blogTitle h1 a:hover,a:active{color:#5c8ec6}#mainContent,#sideBar,#topics{text-overflow:ellipsis;overflow:hidden}#BlogPostCategory a{background:#e8a258}#EntryTag{margin-top:20px}#EntryTag a{background:#6fa3ef}#EntryTag a span,#BlogPostCategory a span{margin-right:3px}.topicListFooter{text-align:right;margin-right:10px;margin-top:10px}#navList a,.dayTitle,button{text-align:center}#home,.inner{margin:0 auto}#divRefreshComments{margin-right:10px;font-size:9pt}*{margin:0}html{height:100%;font-size:62.5%;-webkit-tap-highlight-color:transparent}body{background-color:#fff;font-size:12px;font-family:Merriweather,"Open Sans","Microsoft Jhenghei","Microsoft Yahei",sans-serif;color:#3a4145;-moz-font-feature-settings:'kern' 1;-o-font-feature-settings:'kern' 1;overflow:hidden}body:before{content:'';display:block;z-index:-1;position:fixed;top:0;left:0;right:0;bottom:0;background-size:20px 20px}::-moz-selection{background:#d6edff}::selection{background:#d6edff}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}li{list-style:none}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:400;padding-left:20px}a{outline:0;color:#5c8ec6}a:link,a:visited{color:#5c8ec6;text-decoration:none}a:hover{color:#f60;text-decoration:none}a:active{text-decoration:none}.clear{clear:both}button{width:auto;display:inline-block;padding:.1rem 1.5rem;cursor:pointer;outline:0;text-decoration:none;color:#fff;font-family:'Open Sans',sans-serif;font-size:11px;line-height:13px;font-weight:300;letter-spacing:1px;text-transform:uppercase;text-shadow:none;border-radius:.3rem;border:.1em solid rgba(0,0,0,.05);background:#5ba4e5}b{font-weight:400}#home{width:70%;max-width:900px;background-color:rgba(255,255,255,.9);padding:0 20px 30px;box-shadow:0 0 20px 10px rgba(220,220,220,.3)}#header{padding-bottom:5px;margin-top:10px}#blogTitle{height:60px;clear:both}#blogTitle h1{font-size:26px;font-weight:700;line-height:1.5em;margin-top:20px}#blogTitle h1 a{color:#515151}#blogTitle h2{font-weight:400;font-size:13px;line-height:1.846153846;color:#757575;float:left}#blogLogo{float:right}#navigator{font-size:13px;border-bottom:1px solid #ededed;border-top:1px solid #ededed;height:50px;clear:both;margin-top:25px}#blog-calendar td,#blog-calendar th,.
本节为索引页,无算法内容。
零基础如何入门激光SLAM https://blog.csdn.net/tiancailx/article/details/111358640
数据集链接 https://blog.csdn.net/tiancailx/article/details/115120665
序章 — 为什么要做这个开源项目 https://blog.csdn.net/tiancailx/article/details/109777276
前言 — 我眼中的SLAM https://blog.csdn.net/tiancailx/article/details/109987630
写作计划 https://blog.csdn.net/tiancailx/article/details/110096263
激光雷达数据效果对比 https://blog.csdn.net/tiancailx/article/details/110141867
了解雷达数据 https://blog.csdn.net/tiancailx/article/details/110247279
使用单线雷达实现LIO-SAM中的特征点提取 https://blog.csdn.net/tiancailx/article/details/110502471
使用PCL进行雷达的消息类型转换 https://blog.csdn.net/tiancailx/article/details/110830731
基于ICP的帧间匹配 https://blog.csdn.net/tiancailx/article/details/111031536
基于PL-ICP的帧间匹配 https://blog.csdn.net/tiancailx/article/details/111355512
基于PL-ICP的激光雷达里程计 https://blog.csdn.net/tiancailx/article/details/111593526
栅格地图的构建 https://blog.csdn.net/tiancailx/article/details/112133226
基于GMapping的栅格地图的构建 https://blog.csdn.net/tiancailx/article/details/112179900
基于Hector的栅格地图的构建 https://blog.csdn.net/tiancailx/article/details/112978031
简单重写 Hector SLAM https://blog.csdn.net/tiancailx/article/details/113312856?spm=1001.2014.3001.5501
Hector论文公式推倒与相关代码解析 https://blog.csdn.net/tiancailx/article/details/113522899
使用IMU与轮速计进行单线激光雷达的运动畸变校正 https://blog.csdn.net/tiancailx/article/details/114924197
Karto的前端实现与解读 https://blog.csdn.net/tiancailx/article/details/115573185
Karto的后端优化与回环检测功能对比测试与分析 https://blog.csdn.net/tiancailx/article/details/116017276
Karto的后端优化与回环检测的实现解读 https://blog.csdn.net/tiancailx/article/details/116712959
基于g2o的后端优化的代码实现 https://blog.csdn.net/tiancailx/article/details/121266020
基于ceres的后端优化的代码实现 https://blog.csdn.net/tiancailx/article/details/121334619
基于gtsam的后端优化的代码实现 https://blog.csdn.net/tiancailx/article/details/121358435
总结 https://blog.csdn.net/tiancailx/article/details/121472869
Thonny(免费Python编程学习平台)是专门针对python初学者最新开发的编程学习软件。如何提升Python编程能力?Thonny(免费Python编程学习平台)轻松帮助用户。使用一个友好的IDE,为您提供几个有用的学习工具,所有这些都打包成一个直观的GUI,让你更快的熟悉Python编程语言。
软件特色
容易上手
Thonny内置了Python 3.7,所以只需要一个简单的安装程序,就可以开始学习编程了。(如果有必要,你也可以使用单独的Python安装。) 初始用户界面上没有任何可能分散初学者注意力的功能。
无障碍的变量
当你完成hell-worlds后,选择View → Variables,看看你的程序和shell命令是如何影响Python变量的。
简单的调试器
只需按Ctrl+F5代替F5,你就可以一步一步地运行你的程序,不需要断点。大步按F6,小步按F7。步骤遵循程序结构,而不仅仅是代码行。
通过表达式评估的步骤
如果你使用小步骤,那么你甚至可以看到Python是如何评价你的表达式的。你可以把这个浅蓝色的盒子看成是一张纸,Python 在这里用子表达式的值逐一替换子表达式。
函数调用的忠实表示
步入函数调用会打开一个新窗口,里面有单独的局部变量表和代码指针。良好的理解函数调用的工作原理对于理解递归特别重要。
突出语法错误
未关闭的引号和括号是最常见的初学者语法错误。Thonny的编辑器可以让你很容易发现这些错误。
解释了作用域
高亮显示变量的出现,可以提醒你相同的名称并不总是意味着相同的变量,并且有助于发现错别字。本地变量与全局变量有了直观的区分。
解释引用的模式
变量表最初按照简化模式(名称→值)呈现,但可以切换到更现实的模式(名称→地址/ID→值)。
变量表与值表
代码完成
学生可以通过代码完成的帮助,探索API
初学者友好的系统shell
选择 "工具"→打开系统shell来安装额外的软件包或学习在命令行上处理Python。PATH和与其他Python解释器的冲突由Thonny处理
简单、干净的pip GUI
选择工具 → 管理软件包,更容易安装第三方软件包
sudo apt-get install python-software-properties sudo apt-get update sudo apt install software-properties-common sudo apt-get update
https://github.com/PaddlePaddle/PaddleDetection/tree/release/0.5/configs/solov2
这个算法,使用的是PaddleDetection研发团队深度优化过的实时实例分割算法SOLOv2。经过一系列的优化后,SOLOv2-Enhance(PaddleDetection提供的SOLOv2的增强模型,如图五角星所示)的性能表现如下图所示:
Tesla V100-SXM2 的单GPU环境中预测速度达到38.6FPS,提升了31.2%;COCO val2017数据集上mask AP达到38.8%,提升2.4个百分点;单机8卡训练速度是SOLOv2官方PyTorch版本的2.4倍;在精度和预测速度性价比方面达到业界SOTA级别。 PaddleDetection提供的SOLOv2为何有如此优势呢?下面从实例分割算法、SOLO算法演进历程及PaddleDetection对于SOLOv2深度优化等几方面为大家逐层剖析背后的设计和实现思想。
实例分割算法
实例分割一般分为自上而下和自下而上两种方法。
自上而下的实例分割方法 简单的说,这种方法就是先检测后分割。这类方法的代表选手是Mask R-CNN。它的优点是定位精度高,但也有一定的局限,比如:预测时延高,达不到实时,实例分割结果在物体检测框的束缚下等。
业界很多大神都在持续尝试基于Mask R-CNN算法进行改进,希望解决上述局限问题,GCNet、PANet、HTC、DetectoRS等网络就是在Mask R-CNN算法上优化、演进而来的。但是预测速度慢的问题仍得不到解决。
第一类可以被称为实时的实例分割的模型是YOLACT和YOLACT++,它们基于RetainNet,将实例分割分为两个并行的子任务,采用单阶段的网络结构,使网络计算量尽量小,后者训练54个epoch左右,最终在COCO test-dev数据集上的mask AP达到34.6%,在Titan Xp的GPU环境中达到27.3~33.5FPS。
而CenterMask算法则基于Anchor Free模型FCOS更进一步提升了实例分割的精度和速度,改进了backbone,提出VoVNetV2,同时基于Mask R-CNN的mask分支,引入Spatial Attention-Guided Mask(空间注意力模块),实时的CenterMask-Lite模型在COCO Test-dev数据集上的mask AP达到36.3%,在Titan Xp的GPU环境中达到35.7FPS,成为新的SOTA模型。
自下而上的实例分割方法 这类方法比较好理解,先进行像素级别的语义分割,再通过聚类、度量学习等手段区分不同的实例。PolarMask、SOLO系列算法就是其中的代表。
PolarMask基于FCOS的思想,将回归到检测框四边的距离问题转换为回归基于中心点不同角度的36根射线的距离问题,通过联通整个区域获得分割结果。这种方法创新性很高,但问题也很明显,如:通过角点确定分割区域的方法不够准确,mask AP较低,预测速度也很慢。
而SOLO系列算法经过不断的优化,在精度和预测速度的性价比方面超均越了YOLACT++和CenterMask算法,下面我们就着重介绍一下SOLO系列算法的发展历程及PaddleDetection针对SOLOv2算法进行的优化。
SOLO算法发展历程
SOLO(Segmenting Objects by Locations)算法的核心思想是将分割问题转化为位置分类问题,从而做到不需要anchor(锚框)及bounding box,而是根据实例的位置和大小,对每个实例的像素点赋予一个类别从而达到对实例对象进行分割的效果。
具体而言,就是如果物体的中心落在了某个网格内,该网格就负责预测该物体的语义类别,并给每个像素点赋一个位置类别。
SOLOv1 在SOLOv1中有两个分支:类别分支和mask分支。类别分支预测语义类别;mask分支则分割物体实例。同时,使用FPN来支持多尺度预测,FPN的每一个特征图后都接上述两个并行的分支。
(来自论文《SOLO: Segmenting Objects by Locations》)
其中,类别分支负责预测物体的语义类别,共产出S×S×C大小的预测结果。Mask分支中每个有类别输出的网格(正样本)都会输出对应类别的mask,这里一个通道负责预测一个网格的mask,因此输出维度是H×W×S2。同时基于SOLOv1,作者又提出了Decoupled-SOLO改进算法,将S2个分类器解耦为两组分类器,每组S个,分别对应S个水平位置类别和S个垂直位置类别,优化之后的输出空间就从H×W×S2降低到了H×W×2S,从而降低了网络计算量,如下图(b)所示,最后将两个通道的特征图做element-wise乘,进行特征的融合。
(来自论文《SOLOv2: Dynamic and Fast Instance Segmentation》)
SOLOv2 SOLOv2继承了SOLOv1中的一些设定,将原来的mask分支解耦为mask核分支和mask特征分支,分别预测卷积核和卷积特征,如上图(c)中的Dynamic head所示。
输入为H×W×E的特征,F、E是输入特征的通道数,输出为卷积核S×S×D,其中S是划分的网格数目。
Mask核分支位于预测head内,平行的有语义类别分支。预测 head的输入是FPN输出的特征图。Head内的2个分支都有4个卷积层来提取特征,和1个最终的卷积层做预测。Head 的权重在不同的特征图层级上共享。同时作者在kernel分支上增加了空间性,做法是在第一个卷积内加入了CoordConv,即输入后面跟着两个额外的通道,操作如下图所示。
(来自论文《An Intriguing Failing of Convolutional Neural Networks and the CoordConv Solution》)
在Java程序中,不同的基本数据类型的值经常需要进行相互转换。Java语言所提供的七种数值类型之间可以相互转换,基本数据类型转换有两种转换方式:自动类型转换和强制类型转换。
自动类型转换(隐式类型转换) 自动转换:
将取值范围小的类型自动提升为取值范围大的类型 。 基本数据类型的转换规则
小结:通过上面案例我们可以得出数据类型的转换关系(取值范围从小到大)
(1)当把存储范围小的值(常量值、变量的值、表达式计算的结果值)赋值给了存储范围大的变量时,
int i = ‘A’;//char自动升级为int
double d = 10;//int自动升级为double
(2)当存储范围小的数据类型与存储范围大的数据类型一起混合运算时,会按照其中最大的类型运算
int i = 1;
byte b = 1;
double d = 1.0;
double sum = i + b + d;//混合运算,升级为double
(3)当byte,short,char数据类型进行算术运算时,按照int类型处理
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2;//编译报错,b1 + b2自动升级为int
char c1 = ‘0’;
char c2 = ‘A’;
System.out.println(c1 + c2);//113
(4)boolean类型不参与
强制类型转换(显示类型转换)
将1.5 赋值到int 类型变量会发生什么?产生编译失败,肯定无法赋值。
Topic 处于 under replicated 状态.
server.log 充满:
[2020-11-30 19:00:00,006] WARN Received a PartitionLeaderEpoch assignment for an epoch < latestEpoch. This implies messages have arrived out of order. New: {epoch:0, offset:17990690}, Current: {epoch:4, offset:1547772} for Partition: __consumer_offsets-18 (kafka.server.epoch.LeaderEpochFileCache) [2020-11-30 19:00:00,006] WARN Received a PartitionLeaderEpoch assignment for an epoch < latestEpoch. This implies messages have arrived out of order. New: {epoch:0, offset:139386934}, Current: {epoch:4, offset:6837455} for Partition: __consumer_offsets-9 (kafka.server.epoch.LeaderEpochFileCache) [2020-11-30 19:00:00,006] WARN Received a PartitionLeaderEpoch assignment for an epoch < latestEpoch.
有时候使用脚手架创建的项目,比如vue-cli,会默认使用eslint的一些规则,比如airbnb。其中基本会包含这样一条规则:
"linebreak-style": ["error", "unix"], 这个规则的意思是回车换行符使用unix风格的,也就是LF。unix其实主要就是指mac,或者ubuntu这类的。本来团队都用Mac就没啥问题。但如果你用的是windows。就会有标题中的错误:
(linebreak-style) Expected linebreaks to be 'LF' but found 'CRLF'. (eslint) 但堂堂vue-cli初始化的项目会没考虑到这个问题?当然不会,其实项目中应该还有一个.editorconfig文件,如果没有,你就自己添加一个,并输入如下:
[*.{js,jsx,ts,tsx,vue}] indent_style = space indent_size = 2 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true max_line_length = 100 以上是vue-cli初始化的默认值。详细看下边的注释:
# 缩进使用空格 indent_style = space # 缩进2个字符 indent_size = 2 # 行结尾使用 lf !!!! end_of_line = lf # 删除行尾空格 trim_trailing_whitespace = true # 文件结尾添加一个空行 insert_final_newline = true # 行最大长度 max_line_length = 100 正常情况下,这个文件会约束当前的项目的书写规范。但为什么了windows下没生效呢?因为这个文件需要你的编辑器支持。换言之你需要安装插件!
题外话:正是因为业余接触Python,常专注数小时弄清某件事用python怎样实现,这才催生了一个想法:创设公众号来记录、积累和分享。笔者学习python为目标导向,有需求才会去研究相应模块,知识体系未必扎实完备,优化方面的不足请见谅。
多维动态图表可以直观地展现某几项指标多年来的变化,效果见下图:
想做出这样图表,就要用到我们今天的主角:matplotlib中的animation模块。
简单来说,这个模块帮助你把已有的元素进行分组,每组所有元素构成动态图的一帧。而这个模块本身也非常简单,只有两种函数:FuncAnimation和ArtistAnimation。前者以函数驱动,后者则像堆积木一样一帧一帧堆起来。
本文主要介绍ArtistAnimation。它的各项参数如下:
fig就是目标图表了;artists为一个列表,它的官方解释为“artists : list, each list entry a collection of artists that represent what needs to be enabled on each frame. These will be disabled for other frames.”;最后面是两个系列参数的总称。
简单来说,它的结构就是这样的了,每一个子列表包含众多“Artist”,构成一帧图。那么什么是“Artist”呢?其实matplotlib的制图功能还是非常强大的,柱、饼图说冰山一角好像都有点多了。属于“Artist”类的见下图:
(图片来源:https://matplotlib.org)
不要慌,我们是目标导向,只看自己需要的。
接下来详解code:
为了python支持中文,第一行必不可少。为了matplotlib支持中文,这里换成系统自带字体微软雅黑。
创建一个figure叫“fig”,一个坐标系叫“ax”。ind和width为所画柱状图的参数,依次与位置和宽度有关。
笔者所用数据是从excel摘取,所以使用了xlrd模块。(这模块一搜全会)N就是我们这个图的总帧数,接下来创建3个关键的列表,Pictures用来装柱状图,Years用来装年份,Artists整合前两个列表,形成ArtistAnimation函数所接受的格式。
接下来是主循环。基本操作读数据、处理缺省值、转换成元组tuple。(在bar()函数里,对应参数需要array-like格式)注意从第二个开始运算符变为“+=”,即在第一个基础上再把后面的加上去。使用type()函数我们会发现,单纯plt.bar()做出来的类是matplotlib.container.BarContainer,而多个这种类加起来后则变为tuple,同时之前的单个类转化为matplotlib.patches.Rectangle。如果用类似的方式加上年份,则会报错:
笔者在此提供了一种解决方案:根据官方提供的artist类图表,Text和Rectangle都是一个artist,而tuple是支持索引的,那就把patches这个tuple给拆了,再加上年份,把这所有的一团装在一个新的list里面。这样最大的好处是避免了不同类无法相加的尴尬情境,每一帧的list里面包含这一帧所有的最小单元artist。这样就很简单了,开始堆积木就好了。
加个标题,中文切记引号前要加u,表示utf-8编码。然后横轴标签,以及图例。ArtistAnimation函数让我们做的所有artists分组一帧一帧地呈现。
将做的图呈现出来直接plt.show()就好了,而将做的图完美保存可就有讲究了。推荐使用imagemagick,保存为gif格式,一来文件很小,二来矢量保存伸缩不影响图质。
这东西需要提前安装好。Windows相对容易,在MacOS或者Linux系统下则需要先安装Homebrew,这和pip类似是包管理器。
粘贴这一行到终端敲回车就可以了,挺酷的。
有了homebrew就可以这样直接安装imagemagick了。
成功安装好imagemagick就可以像刚刚那样直接保存为gif格式的动态图表啦!
以上是柱状图的code,饼图更简单一些,就不过多赘述了。
使用JNA调用C/C++函数的步骤: 1、定义JNA接口API(C/C++).h文件
2、实现.h文件中定义的函数(.c)文件
3、编译.c文件,生成动态库文件(.so)
4、应用JNA的包jna-*.jar,我这里用的是jna-5.6.0.jar
5、定义java接口,加载动态库,并定义相应的API方法
6、通过java接口,调用相应的方法
今天测试了,java和C/C++函数之间一维数组和二维数组的传参。
一维数组 一维数组比较简单,直接上代码:
1、testJNA.h
#include <stdio.h> void printfArray(int arr[]); 2、testJNA.c
#include "testJNA.h" void printfArray(int arr[]) { printf("input【%d】",arr[0]); } 3、Clibrary.java
import com.sun.jna.Library; import com.sun.jna.Native; public interface Clibrary extends Library { Clibrary INSTANCE = (Clibrary) Native.load("testJNA", Clibrary.class); void printfArray(int[] arr); } 4、调用
public static void main(String[] args) { int[] a = new int[]{1,2}; Clibrary.INSTANCE.printfArray(a); } 二维数组 二维数组比较麻烦,因为JNA不能自动将java的二维数组转换成C的二维数组(也许支持,本人不熟悉没有找到相应的方法,如果更好方法,还请留言指教),我在这里自定义了一个对象
1、testJNA.h
#include <stdio.h> typedef struct { int a[2]; }Ershuzu; void printfERArray(Ershuzu arr[],int size); 2、testJNA.
数据卷 docker run -it --name volume-test1 -h nginx -v /data centos
说明: -i 终端保持打开 -h 指定主机名为nginx , --name: 指定容器名称 -v 指定 数据卷名称 /data 挂载了一个 /data 目录
Docker 直接将 /data 目录挂载到了物理主机上查看 volume-test1 容器信息,挂载到物理机的什么位置上
方式一 : docker inspect -f {{.Volumes}} volume-test1 ,改成 .Config.Volumes 依旧查询不到。
直接看容器的所有信息 再grep
物理机上创建文件,可以映射到 容器中。 指定一个目录,挂载到容器里面
docker run -it --name volume-test2 -h nginx -v /opt:/opt centos 将物理主机上的 /opt 挂载到 容器上的 /opt目录 数据卷容器 启动一个容器数据卷来源于另外的一个容器 (源容器为volume-test1 目标容器为 volume-test4 )
docker run -it --name volume-test4 --volumes-from volume-test1 centos 这里启动的volume-test4里就有之前在 volume-test1 容器里使用物理映射创建的 haha文件。 Docker容器手动构建 nginx 首先需要启动一个centos的镜像容器
在使用python连接redis的时候,报错 redis.exceptions.ConnectionError: Error 10060 connecting to IP:port. 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。
PING了一下redis所在的服务器,能够PING通,再检查redis的连接认证,确认无误后,依旧报错连接不上。
考虑是Linux防火墙没有开放该端口,于是试一下
iptables -I INPUT -p tcp --dport 6666 -j ACCEPT
再连接,就可以了
1.TCP/IP的三次握手和四次挥手 三次握手:
第一次握手:客户端向服务端发送SYN码数据包,表示客户端要求和服务端建立连接;
第二次握手:服务端收到客户端的连接请求后,会发送ACK数据包给客户端,表示你的连接 请求已经收到,询问客户端是否真的需要建立连接;
第三次握手:客户端收到ACK码以后会检验是否正确,如果正确,客户端会再次发送ACK码给 服务端,表示确认建立连接;
(三次握手都成功以后才会建立连接,然后才会发送数据;)
四次挥手:
第一次挥手:当客户端发送数据结束后,会发送FIN码数据包给服务端,表示告知服务端客 户端的数据已经传递完了。
第二次挥手:当服务端收到FIN后,会发送ACK给客户端,表示服务端已经知道客户端传完
了。客户端收到ACK以后就会把传递数据给服务端的通道关闭;
第三次挥手:当服务端把响应的数据发送完毕后,会发送一个FIN给客户端,告知客户端响 应的数据已经发送完毕;
第四次挥手:当客户端收到FIN后,会发送一个ACK码数据包给服务端,告知服务端客户端已
经知道数据发送完毕;服务端收到ACK码后,可以安心的把数据传递通道关闭掉。
2.http常用状态码(http-status-code):
2xx:表示成功
200 OK 表示所有东西都正常
204 表示请求成功,但是服务端没有内容给你
3xx: 表示重定向
301,Moved Permanently。永久重定向(当访问一个永久重定向的网站的时候,一个域名被指向一个其他网站,且是永久的),该操作比较危险,需要谨慎操作:如果设置了301,但是一段时间后又想取消,但是浏览器中已经有了缓存,还是会重定向。302,Fount。临时重定向,但是会在重定向的时候改变 method: 把 POST 改成 GET,于是有了 307304 走缓存(服务端觉得你之前请求过这个东西,而且服务器上的那一份没有发生变化,告诉客户端用缓存 就行)307,Temporary Redirect。临时重定向,在重定向时不会改变 method 4xx: 表示客户端错误
400 参数传递不当,导致的错误
401 权限不够导致的
403 服务端已经理解请求,但是拒绝响应
404 客户端请求的资源或者数据不存在(发现请求接口404,有两种情况一种是咱们写错接口了或者服 务端还没部署)
5xx: 表示服务端错误(遇到以5开头的错误去找服务端错误)
500 服务端内部错误
502 网关错误
3.从浏览器输入URL按回车到页面显示都发生了什么?
浏览器根据URL进行DNS查询 首先从DNS缓存中查询若未在缓存中找到,则不停的向上一级级请求DNS服务器 取得IP地址,建立TCP连接构造HTTP请求报 添加一些HTTP首部根据同源政策添加cookie 在TCP连接上发送HTTP报文,等待响应服务器处理HTTP请求报文,返回响应HTTP响应报文浏览器处理服务器返回的HTTP响应报文,若为HTML则渲染页面,不包括脚本的简单渲染流程如下 解析DOM、CSSOM根据DOM、CSSOM计算render tree根据render tree进行layoutpaint,至此,用户可以看到页面了 4.HTTPS和HTTP的区别主要如下?
HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
服务器上配置 1. 开启docker远程访问
cd /lib/systemd/system
sudo vim docker.service
#替换或修改:127.0.0.1(本地网络访问)换成0.0.0.0表示不限制访问地址 [Service] ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 2. 重载配置
systemctl daemon-reload
3. 重启docker 服务
systemctl restart docker.service
4. 开放端口(,阿里云配置访问规则,本地telnet试试能否连通)
ubuntu命令:
sudo ufw allow 2375 centos命令:
firewall-cmd --zone=public --add-port=2375/tcp --permanent
systemctl restart firewalld windows配置 1. 配置用户环境变量
2. IDEA设置
需要先下载IDEA的docker插件,在插件市场直接安装即可
项目设置 1. pom文件
加入docker打包插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin> <plugin> <groupId>com.spotify</groupId> <artifactId>dockerfile-maven-plugin</artifactId> <version>1.4.13</version> <executions> <execution> <id>default</id> <goals> <goal>build</goal> <goal>push</goal> </goals> </execution> </executions> <configuration> <repository>${project.
说 HashTable 是PHP的灵魂,一点也不为过。在Zend引擎中,比如变量表、常量表、函数表、数组,以及资源管理、线程安全等,其实现都有HashTable的身影。HashTable 是一种查找性能极高的数据结构,理想情况下其算法复杂度是O(1)。
PHP 源码信息
PHP 版本:php-5.6.17头文件: Zend/zend_hash.h,源文件: Zend/zend_hash.c注意:说明中使用了伪代码形式,只有代码块中的代码才可以执行 PHP HashTable 概述
有两部分组成,Bucket 和 HashTable,而且均为结构体(struct)。Bucket 是存储数据的单元,用于保存具体的数据内容;HashTable 用于保存整个哈希表需要的基本信息。二者关系可以简单理解为:HashTable = Array(); HashTable['arBuckets'] = [Bucket1, Bucket2, Bucket3, …]。HashTable 的目的就是通过索引把每个Bucket元素分散到唯一的位置。PHP 内核通过HashTable 结构管理Bucket 数组。相比普通HashTable,PHP的HashTable同时维护一个双向链表。在HashTable.arBuckets 存储的是包含多个Bucket指针的向量,每个指针又指向一个双向链表(多个bucket组成)。 HashTable 源码展示
在Zend/zend_hash.h的line 55~83 中定义了结构体 Bucket 和 HashTable。注意 Bucket 和 HashTable 是别名,分别对应结构体 bucket 和 _hashtable。
Bucket 解析说明
先分析一下Bucket 结构体成员变量的作用:
说明
一. pData 和 pDataPtr 的关系,
pData 指向的是保存数据的内存块地址,一般通过malloc等分配;pDataPtr 如果是指针数据,此值会指向真正的value,同时pData 会指向该值疑问 内存块地址,不也是指针吗?和pDataPtr什么区别?? 二. h 成员保存的是HashTable key 哈希后的值,而非HashTable中的索引值,为什么?
索引值和HashTable的容量有关系,如果HashTable扩容,那么这些索引还得重新进行哈希,再进行索引映射数字索引直接就可以作为哈希表的索引,数字也无需进行哈希处理HashTable 解析说明
背景:之前我在我的电脑上面使用git一直是正常的,考试月一整个月没用,今天用的时候发现出现了一个奇怪的问题
这就搞得我很烦了,于是上网查了一些资料之后终于弄懂了,写一篇文章记录一下。
排查过程 首先我的ssh密钥是肯定没问题的,因为我压根就没有动过它我想到了之前由于我在github上部署了一个在线简历网站,后来又想在github上面部署一个博客,于是申请了一个小号,然后通过Host来区分我的小号与大号,会不会是这里出问题了呢?
之后把小号的注释掉了,接着尝试,发现还是这样,没有用。后来想了一下,之前小号与大号都push过,没问题啊,怎么可能是这里出的问题是吧!于是我上stackoverflow查了一下,应该得知问题的原因了,就是防火墙把你的这个22号端口禁用了,所以你修改配置更换一个端口就可以了,这个配置文件在你用户目录下面的.ssh目录下面的config文件,在里面加上这样几行就可以了
其他csdn博客里面有介绍一些别的方法,把ssh该成https,这个方法其实治标不治本,因为github支持两种协议,ssh与https,所以可以这么做,但是我翻墙软件的缘故,我的https基本上用不了,因为很慢,我改了代理之后就不能访问,很是鸡肋 总结一下,出现这个问题就是因为22端口不能用,换一个端口就好了,我也不知道我上面一大通在说什么
参考文章
前面的文章讲了二分查找算法,这种算法使用了一种非常常见的思想–"分治思想"。所谓分治,就是"分而治之",当解决一个大问题时,如果问题太大而无法直接解决,就可以试着把问题分解成很多个相互独立的子问题,将每个子问题各个击破,最后每个子问题得到的结果一合并就得出了原问题的结果,分治法一般都通过递归实现。本文讲解的归并排序就是分治思想的经典应用。
一.基本思想 1. 分解:给出包含若干个数的一段序列。按照分治思想要把序列分成两部分,然后对每个部分,再以相同的方式分成两个更小的序列。就这样一直分下去,到最后每段序列都只有一个数了。无法再分解了,那该怎样排序呢?答案是不用排序了,每个序列都只有一个数还怎么排序呢,换句话说,只有一个数,这本身就是有序的。这就是分治算法的妙处,把一个无序的序列分成了若干个有序的序列。
2. 合并:合并是整个排序算法的难点和重点。阐述起来很简单,就是把分开的子序列两两按序合并。
· 说起来很简单,要想真正的理解并不容易,以图解的形式描述归并的过程更直观一些。
二.图解 分解的步骤很简单。
把整个序列分成多个仅有一个数的序列后,开始合并。
第一趟合并
第二趟合并
第三趟合并
在不断合并的过程中,序列中的元素就自动排好了序。
三.具体实现 上述就是归并排序的思路,那具体是如何实现的呢?
我们要先定义一个临时数组b[],我们将被排序的数组命名为数组a[]。在两个序列合并的过程中,要先将两个序列中的元素进行比较,再按顺序存放到临时数组b[]中,这样b[]中的元素就是有序的,再将b[]中的数组复制到a[]中。以最后一次合并为例(由于合并的两序列也都经过了多次比较和合并之后才形成,所以也是有序的)
注:下文的比较过程中用的首个元素并不是序列本身的首个元素,序列本身的首个元素是固定不变的,这里的首个元素是序列中未进行比较的元素中的首个元素。
(1)第一次比较,4<7,4放入临时数组,12变成了第一个序列的首个元素。
(2)第二次比较,7<12,7放入临时数组,16变成了第二个序列的首个元素。
(3)第三次比较,12<16,12放入临时数组,13变成了第一个序列首个元素。
(4)第四次比较,13<16,13放入临时数组,50变成了第一个序列的首个元素。
(5)第五次比较,16<50,16放入临时数组,25变成了第二个序列的首个元素。
(6)第六次比较,25<50,25放进临时数组,33变成了第二个序列的首个元素。
(7)第七次比较,33<50,33放进临时数组,第二个序列的元素全部被安排了。
(8)第八次比较,发现第二个序列都比完了,这时候就把第一个序列中的剩余元素(其实也就一个了)按序放进数组。
这段过程的实现代码为
private static void Merge(int a[],int low,int mid,int high){ int[] b=new int[high-low+1];//开临时数组 int i=low,j=mid+1,t=0,t1=0;//i,j分别作为两部分的指针 while(i<=mid&&j<=high){//两部分比较,小的进临时数组 if(a[i]>a[j]){ b[t++]=a[j++]; }else { b[t++]=a[i++]; } } while(i<=mid) b[t++]=a[i++];//如果有一方元素比较完了,另一方的元素直接塞进去 while(j<=high) b[t++]=a[j++]; for(i=0;i 四.代码 import java.util.Scanner;public class Sort { public static void main(String[] args) { Scanner sc=new Scanner(System.in); int n=sc.
目录 伪代码复杂度分析(最坏情况)源代码(有详细注释)演示 Binary Insertion Sort是在搜索位置时使用binary search二分查找法的insertion sort插入排序,其最好情况是O(n),最坏情况O(nlogn),属于in-place,空间复杂度O(1),稳定。 直接上本人的小小homework:(本来是英文的,就机翻一下吧) 伪代码 BinaryInsertionSort(A[0,...,n-1]) //Implement insertion sort with binary search which find the position //Input: An unsorted array A[0...n-1] //Output:A sorted increasing array A[0...n-1] //带有二进制搜索的插值插入排序,以找到位置 //输入:一个未排序的数组A[0.n-1] //输出:排序递增数组A[0.n-1] for keyIndex←1 to n-1 do insertIndex←binarySearch(A, keyIndex) //返回的是应该插入的位置 //对插入位置~当前key在的位置进行移位 temp←A[keyIndex] j←keyIndex while j>insertIndex do A[j]←A[j-1] j←j-1 A[insertIndex]←temp return A BinarySearch(A[0...n], keyIndex) //Find the position to insert the key, indicated by keyIndex of the array, in the sorted part of array, which is index from 0 to keyIndex - 1 //Input:An array A[0.
问题:
Permission denied: user=dr.who, access=READ_EXECUTE, inode="/tmp":root:supergroup:drwx-wx-wx
原因:
权限不够 解决办法:
root@master:/usr/local/hadoop# hdfs dfs -chmod -R 755 /tmp
这个错误大概率是我系统的问题,onnx编译需要用到protobuf,而我系统里面的protobuf版本是3.0.0,但是onnx里面用到了新版本protobuf的函数,在编译的时候会报链接找不到库的问题** _ZNK6google8protobuf7Message11GetTypeNameEv **
所以我从网上下载了3.6.1版本的protobuf进行编译安装,然后删除了系统自带的protobuf sudo apt purge libprotobuf-dev,再运行cmake的时候提示protobuf找不到,查看cmake的记录,提示是在系统安装的cmake里面有个 * /usr/share/cmake-3.10/Modules/FindProtobuf.cmake * 文件,这个文件是是cmake查找protobuf的Module,这个问题可以通过在onnx的顶层CMakeLists.txt文件里面添加 *set(Protobuf_INCLUDE_DIR “/usr/local/include”)*来解决。
文章目录
1 next数组 1.1 概念1.2 暴力求解next数组1.3 递推求解next数组 1.3.1 总结思路1.3.2 模版代码2 KMP 2.1 概念2.2 暴力求解 O(nm)2.3 KMP O(n+m) 2.3.1 思想2.3.2 模版思路2.3.3 模版代码2.3.4 统计模式串在文本串出现的次数 2.3.4.1 思想2.3.4.2 实现代码2.3.4.3 时间复杂度计算2.4 nextval数组 2.4.1 概念2.4.2 模版代码3 从有限状态自动机(AC自动机)看KMP 1 next数组
1.1 概念
假设有一个字符串s(下标从0开始),那么它以i号位结尾的子串就是s[0…i]。对于该子串来说,长度为k+1的前缀和和后缀和分别为s[0…k]和s[i-k…i]。
现定一个一个int型数组next,
next[i]表示:使子串s[0…i]的前缀和s[0…k]等于后缀和[i-k…i]的最大k(前缀和和后缀和可以重叠,但不能是s[0…i]本身);如果找不到相等的前后缀和,那么就令next[i] = -1。显然,next[i]就是所求最长相等前后缀和中前缀最后一位的下标。 1.2 暴力求解next数组
以字符串s = “ababaab”为例子,next数组的计算过程如下图所示:
图中,上框直接用下划线画出了子串s[0…i]的最长相等前后缀和,而下框将子串s[0…i]写成两行,让第一行提供后缀,第二行提供*前缀,然后将相等的前后缀框起来。
1 当i=0:子串s[0…i]为“a”,由于找不到相同的前后缀和(前后缀均不能是字符串本身,下同),令next[0] = -1;2 当i=1:子串s[0…i]为“ab”,由于找不到相同的前后缀和),令next[1] = -1;2 当i=2:子串s[0…i]为“aba”,能使前后缀相等的最大k为0,此时后缀s[i-k…i]为“a”,前缀s[0…k]也为“a”,而当k=1,后缀s[i-k…i]为“ba”,前缀s[0…k]也为“ab”,它们不相等。令next[2] = 0;3 当i=3:子串s[0…i]为“abab”,能使前后缀相等的最大k为1,此时后缀s[i-k…i]为“a”,前缀s[0…k]也为“a”,而当k=2,后缀s[i-k…i]为“bab”,前缀s[0…k]也为“aba”,它们不相等。令next[3] = 1;4 当i=3:子串s[0…i]为“abab”,能使前后缀相等的最大k为1,此时后缀s[i-k…i]为“a”,前缀s[0…k]也为“a”,而当k=2,后缀s[i-k…i]为“bab”,前缀s[0…k]也为“aba”,它们不相等。令next[3] = 1;5 当i=4:子串s[0…i]为“ababa”,能使前后缀相等的最大k为2,此时后缀s[i-k…i]为“aba”,前缀s[0…k]也为“aba”,而当k=3,后缀s[i-k…i]为“baba”,前缀s[0…k]也为“abab”,它们不相等。令next[4] = 2;6 当i=5:子串s[0…i]为“ababaa”,能使前后缀相等的最大k为0,此时后缀s[i-k…i]为“a”,前缀s[0…k]也为“a”,而当k=1,后缀s[i-k…i]为“aa”,前缀s[0…k]也为“ab”,它们不相等。令next[5] = 0;7 当i=6:子串s[0…i]为“ababaab”,能使前后缀相等的最大k为1,此时后缀s[i-k…i]为“ab”,前缀s[0…k]也为“ab”,而当k=2,后缀s[i-k…i]为“aab”,前缀s[0…k]也为“aba”,它们不相等。令next[6] = 1, 由此可以得出next[i]就是子串s[0…i]的最长相等前后缀的前缀最后一位的下标。
操作题 Vue 两个等号 == 和三个等号 === 的区别 == 用于比较两者是否相等,忽略数据类型。 === 用于更严谨的比较,值和值的数据类型都需要同时比较。 为什么vue中data必须是一个函数 https://blog.csdn.net/xyphf/article/details/88863059 Vue中v-model与:value的区别 v-model不可以加其他值:<input type="text" v-model="curAmount"> :value可以加 单位:<input type="text" :value="curAmount+'元'"> var,let,cont声明变量的区别 https://www.cnblogs.com/bonly-ge/p/9262723.html 在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量。 全局变量:在函数外声明的变量作用域是全局的。全局变量在JS任何地方都可以访问。 ES2015(ES6) 新增加了两个重要的 JS关键字: let 和 const。 let 声明的变量只在 let 命令所在的代码块内有效。 const 声明一个只读的常量,一旦声明,常量的值就不能改变。 函数内使用 var 声明的变量只能在函数内容访问,如果不使用 var 则是全局变量 使用 var 关键字声明的全局作用域变量属于 window 对象 var 关键字定义的变量可以在使用后声明,也就是变量可以先使用再声明。 let 关键字定义的变量需要先声明再使用。声明的变量只在 let 命令所在的代码块内有效。 const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改。 vue中 require和import区别 https://www.cnblogs.com/caiguangbi-53/p/11757508.html let echarts = require('echarts/lib/echarts') 这里require直接从 node_modules 中查找文件位置进行引入 vue中 ref 和 $refs 的介绍与使用 https://blog.
python - 如何使用b将文件上传到S3存储桶中的目录
我想使用python在s3存储桶中复制一个文件。
例如:我有桶名=测试。 在桶中,我有2个文件夹名称“dump”&amp;“输入”。 现在我想使用python将文件从本地目录复制到S3“dump”文件夹...任何人都可以帮助我吗?
10个解决方案
81 votes
试试这个...
import boto
import boto.s3
import sys
from boto.s3.key import Key
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
bucket_name = AWS_ACCESS_KEY_ID.lower() + '-dump'
conn = boto.connect_s3(AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY)
bucket = conn.create_bucket(bucket_name,
location=boto.s3.connection.Location.DEFAULT)
testfile = "replace this with an actual filename"
print 'Uploading %s to Amazon S3 bucket %s' % \
(testfile, bucket_name)
def percent_cb(complete, total):
sys.stdout.write('.')
sys.stdout.flush()
k = Key(bucket)
k.key = 'my test file'
实现简单的ARP扫描工具: 传入扫描参数main.py -a 192.168.1.1-100 扫描网段内所有的在线主机并显示其MAC地址.
from scapy.all import *
from optparse import OptionParser
import threading
def parse_ip(targets):
_split = targets.split('-')
first_ip = _split[0]
ip_split = first_ip.split('.')
ipv4 = range(int(ip_split[3]),int(_split[1])+1)
addr = [ ip_split[0]+'.'+ip_split[1]+'.'+ip_split[2]+'.'+str(p) for p in ipv4 ]
return addr
def arp_scan(address):
try:
ret = sr1(ARP(pdst=address),timeout=5,verbose=False)
if ret:
if ret.haslayer('ARP') and ret.fields['op'] == 2:
print('[+] IP地址: {} => MAC地址:{}'.format(ret.fields['psrc'],ret.fields['hwsrc']))
except Exception:
exit(1)
if __name__ == "__main__":
parser = OptionParser()
0. 直方图优化算法 XGB在计算树节点信息增益的时候,使用了预排序的方法来进行节点分裂,这样计算出的分裂节点比较精确,但也造成了很大的时间开销。因此,LightGBM选择了基于直方图的优化算法。
类别特征如何转为直方图:对于分类特征来说,则是每一种取值放入一个bin,且当取值的个数大于max bin数时,会忽略那些很少出现的category值。在节点分裂的时候,这时候就不需要按照预排序算法那样,对于每个特征都计算#data遍了,而是只需要计算#bins遍,这样就大大加快了训练速度。
算法伪代码:
最外面的 for 循环表示的意思是对当前模型下所有的叶子节点处理,需要遍历所有的特征,来找到增益最大的特征及其划分值,以此来分裂该叶子节点。在某个叶子上,第二个 for 循环就开始遍历所有的特征了。对于每个特征,首先为其创建一个直方图。这个直方图存储了两类信息,分别是每个bin中样本的梯度之和$H[f.bins[i]].g$,还有就是每个bin中样本数量$H[f.bins[i]].n$。第三个 for 循环遍历所有样本,累积上述的两类统计值到样本所属的bin中。即直方图的每个 bin 中包含了一定的样本,在此计算每个 bin 中的样本的梯度之和并对 bin 中的样本记数。
1. 性能相关 1.1 减少分割增益计算量 对于XGB,在计算最佳分割点(非近似直方图算法)需要O(#data)次的计算。即计算一个最佳的分裂增益为O(#data*#features)。而对于LGB,直方图算法只需要计算0(#bins*#features)
1.2 直方图作差加速 在二叉树中可以通过利用叶节点的父节点和相邻节点的直方图的相减获得该节点的直方图。所以,仅仅需要为一个叶子节点建立直方图,相邻节点可以通过直方图作差来进行加速。 1.3 减少内存使用 将连续的值替换为discrete bins。若bins足够小,可以利用较小的数据类型来进行存储。比如unit8_t。
XGB需要对数据进行预排序,需要额外的空间存储特征值到样本的索引信息。
1.4 减少并行学习的通信代价 2. 准确率相关 2.1 Leaf-Wise生长策略 与Level-Wise生长策略作对比
2.2 类别特征的最优分割 3. 并行学习的优化 3.1 特征并行 传统的特征并行算法如下:
垂直划分数据,不同的机器有不同的特征集在本地特征集中寻找局部的最佳分割点本地进行各个划分的通信整合并得到最佳的划分在某个机器X上以最佳的划分对数据进行划分,(需要注意:其他线程或者woker不具有该特征的数据信息,因为特征平均分配在各个worker, 各个worker的特征没有交集)。既然其他机器无法根据选出的特征最佳切分进行划分,那么其他节点怎么划分呢?答案是:在机器X上进行划分后,将划分结果通知给其他机器,这样会增大通信开销。其他线程或者worker对接收到的数据进行划分。 以上方案缺点:split finding计算复杂度很高为O(data),当数据量很大的时候,非常慢。其次,有很大通信开销。
LightGBM如何解决?LGB让每个线程拥有所有的数据。因此,LightGBM中没有数据划分结果的通信开销,只要知道最佳的分割点,因为每个线程都有所有数据,可以在线程本地进行切分。过程如下:
每个线程都在本地数据集上寻找最佳的分割点(每个线程负责不同的特征的计算)本地进行各个划分的整合,找到全局的最佳划分每个节点拿到最佳划分后,执行最佳切分。 注意:该特征并行算法在数据量很大时,每个机器存储所有数据代价很高。因此,在数据量很大时,建议使用数据 并行的策略。
3.2 数据并行 传统的数据并行算法如下: 水平划分数据线程以本地数据构建本地直方图将本地直方图整合成全局直方图在全局直方图中寻找最佳划分,然后执行此划分 以上缺点:
高通讯开销。机器合并直方图时,每个机器需要和其他剩下的所有机器通信,整合成全局直方图。那么通信开销为O(#machine*#feature*#data)
LightGBM如何解决?不同于整合所有本地直方图以形成全局直方图的方式,LIghtGBM使用分散规约(Reduce Scatter)的方式。将合并直方图的任务分摊到不同的机器,对不同机器的不同特征(不重叠的)进行整合。然后线程从本地整合直方图中寻找最佳划分到并同步到全局最佳的划分中?什么意思呢?举个例子如下:
本文概述
你是否考虑过Google如何创建与你的喜好相近的推荐电影?它如何为你”弄清楚”呢?好了, 阅读这篇文章后, 你将能够知道专有技术。更好的是, 你将能够自己构建推荐系统。
作为网络创建者, 每个python开发人员都必须了解一些事情, 例如pandas和numpy库。本文中使用的初学者程序甚至无法与行业标准相提并论。因此, 它仅用作系统介绍。我们假设读者具有Python的先前经验。
什么是推荐系统?
推荐系统是一种基本计算, 旨在通过检测数据集中的相关性为客户提供最相关的信息。该算法评估元素, 并向用户显示接近其偏好的高度项目。
Netflix和亚马逊是此类推荐系统的最佳示例。每当你在Amazon上选择商品时, 它就会自动开始向你显示你可能想要的其他商品。 Netflix及其为你推荐电影的选项也是如此。
有三种构建推荐系统的方法:
基于受欢迎程度的推荐人系统
推荐人基于内容的系统
基于相似度的推荐人系统
用python构建一个简单的推荐系统
在此基本推荐器系统中, 我们使用的是电影镜头。这是一个基于相似度的推荐系统。如果愿意, 可以使用PyCharm或Skit-Learn, 并了解为什么pycharm对于每个python程序员都变得越来越重要。因此, 进入第一步, 导入numPy和pandas是我们的首要任务。
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
随后, 我们在数据集中使用pandas read_csv()实用程序。数据集与选项卡分开, 因此sep参数在\ t中传递。然后, 我们转到名称参数。
df = pd.read_csv('u.data', sep='\t', names=['user_id', 'item_id', 'rating', 'titmestamp'])
让我们搜索数据头以查看我们所关注的数据。
df.head()
如果我们能看到电影的标题而不是仅仅处理ID, 那将很容易。加载电影标题并合并数据集;
movie_titles = pd.read_csv('Movie_Titles')
movie_titles.head()
由于item_id的列都是相同的, 因此可以将这些数据集合并到此部分中。
df = pd.merge(df, movie_titles, on='item_id')
df.head()
让我们看一下每一列的表示形式:
VRRP(虚拟路由冗余协议)是一种容错协议,是由一台以上的路由器或三层交换机虚拟成一台路由器,来增加网关可靠性的协议。
本文对VRRP的常见故障及排除方法进行简单介绍。
一、 VRRP协议常见的故障
设备Log日志里出现VRRP配置错误的信息同一个VRRP组内出现多个主设备主从设备的VRRP状态同时频繁切换主设备状态不变,从设备状态频繁切换 二、 VRRP协议故障排除的一般方法
1、设备Log日志里出现VRRP配置错误的信息
VRRP相关的Log日志主要由IP地址冲突,VRRP配置错误和认证失败等几种Log日志信息,其故障排除步骤如下:
使用命令display vrrp verbose查看各交换机的VRRP配置信息,保证VRRP组中所有设备的VRRP配置参数一致。使用debug vrrp packet查看接收到的VRRP调试信息,可以找到VRRP配置错误的设备。 2、同一个VRRP组内出现多个主设备
若短时间内存在多个主设备,属于正常情况,无需人工干预。 若多个主设备长时间共存,这很有可能是由于VRRP组内各设备之间收不到VRRP报文,或者收到不合法的报文造成的,可以采取下列方式排查:
在VRRP主从设备之间使用“ping 接口时间IP地址”的操作 如果ping不通,检查VRRP主从设备之间的网络连接是否正确;如果能ping通,使用命令display vrrp verbose检查VRRP的配置是否一致,对于同一个VRRP备份组的配置,必须要保证虚拟IP地址个数、每个虚拟IP地址、通告报文的发送时间间隔和认证方式完全一样。
查看设备系统资源 使用命令display cpu-usage,查看设备系统CPU资源的使用情况,如果设备CPU使用率过高,可能存在网络攻击或广播风暴造成VRRP协议不能被及时处理,要查找相关原因。
3、主从设备的VRRP状态同时频繁切换
产生该故障的原因一般是由于VRRP组使能监视接口功能后,被监视端口状态不稳,使VRRP主设备的优先级频繁变化,而造成VRRP状态的频繁切换。
使用命令display vrrp verbose命令检查VRRP的参数设置,检查是否在VRRP组中启用了监视端口的功能。检查被监视端口连接线路状态或使用VRRP的非抢占模式。 4、主设备状态不变,从设备状态频繁切换
产生该故障的原因一般是由于VRRP从设备没有能够及时收到或者及时处理VRRP协议报文所致,可以采取以下方式排查:
在从设备ping主设备的接口实际地址。如果ping报文丢包严重或延时过大,需要先检查VRRP设备之间的心跳线及其互联端口状态,也可以增加VRRP协议报文的发送时间间隔或设置抢占延迟来解决。如果ping报文能够正常返回,则需要检查从设备的资源使用情况,如CPU、内存使用率。
最近,不少网友都在后台给小编留言,希望可以分享一下miui9升级教程,那么,miui9怎么升级?今天的教程中,小编就给大家带来miui9升级的2个方法,这两个方法分别是:卡刷和线刷,需要说明的是:目前,暂时只有XIAOMI6和 红米note4 X高通版有推送,红米Note4X联发科版‘MTK’也没有推送。
一、卡刷教程:(无需解锁无需电脑) 1、在MIUI论坛–》MIUI下载,下载自己对应型号的最新开发版zip包;
2、将zip包放到内置存储/downloaded_rom文件夹下,然后进入“系统更新”,点右上角“。。。”选择“手动选择安装包”,然后选择zip包确认升级;
3、升级完成后重启等待推送miui87.8.3内测版‘也就是miui9’。
二、线刷教程:(需要解锁需要电脑) 1、在MIUI论坛下载好‘通用解锁工具’解压,然后在手机进入“设置–》开发者选项–》设备解锁状态”中绑定账号和设备,在手机关机状态下,同时按住音量下+电源键进入Fastboot模式将手机USB连接电脑,在电脑打开通用解锁工具点击解锁;
2、线刷Fastboot完整包下载完成后解压,打开线刷Fastboot完整包文件夹,复制地址栏地址;
3、在MIUI论坛下载‘通用刷机工具’安装好(如遇到系统安全提示一直选择允许安装就好),打开通用刷机工具中的XiaoMiFlash.exe将复制的内容粘贴到蓝色区域位置。
点击黄色圈选部分加载设备,刷机程序会自动识别手机,点击红色圈选部分刷机开始刷机。
4、刷机完成后等待推送miui87.8.3内测版‘也就是miui9’
升级miui9的前提是内测审核通过的或已兑换资格的且论坛已收到升级权限提醒的,刷完开发版才会有推送。
刷机前请备份好你的手机,以免你的手机数据丢失,而且建议大家选择卡刷比较简单。
创建表的时候,字段尽量不要为NULL
解决办法就是设置字段为NOT NULL,并设置字段的默认值。字段尽量不要为NULL的原因如下:
a、NULL需要占用额外的空间存储;
b、进行比较的时候会更复杂,还会导致你select (column)的时候不准确
c、含有NULL值的列,会对SQL优化产生影响,尤其是组合索引中
具体NULL会带来的问题大家可以查阅:https://dev.mysql.com/doc/refman/5.7/en/problems-with-null.html
正确招式:NOT NULL DEFAULT 'xxxxx';
version: '3.5'
services:
rmqnamesrv:
image: foxiswho/rocketmq:server
container_name: rmqnamesrv
ports:
- 9876:9876
volumes:
- ./data/logs:/opt/logs
- ./data/store:/opt/store
networks:
rmq:
aliases:
- rmqnamesrv
rmqbroker:
image: foxiswho/rocketmq:broker
container_name: rmqbroker
ports:
- 10909:10909
- 10911:10911
volumes:
- ./data/logs:/opt/logs
- ./data/store:/opt/store
- ./data/brokerconf/broker.conf:/etc/rocketmq/broker.conf
environment:
NAMESRV_ADDR: "rmqnamesrv:9876"
JAVA_OPTS: " -Duser.home=/opt"
JAVA_OPT_EXT: "-server -Xms128m -Xmx128m -Xmn128m"
command: mqbroker -c /etc/rocketmq/broker.conf
depends_on:
- rmqnamesrv
networks:
rmq:
aliases:
- rmqbroker
rmqconsole:
image: styletang/rocketmq-console-ng
container_name: rmqconsole
ports:
- 8080:8080
第一步通过docker-compose安装mysql,需要两个数据库 1.master的mysql的docker-compose.yml
version: '3.1'
services:
db:
restart: always
image: mysql:5.7.22
container_name: mysql-master
ports:
- 3306:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--default-authentication-plugin=mysql_native_password
--sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
--max_connections=3600
volumes:
- ./data:/var/lib/mysql
user: root
2.slave的mysql的docker-compose.yml
version: '3.1'
services:
db:
restart: always
image: mysql:5.7.22
container_name: mysql-master
ports:
- 3307:3306
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
command:
--character-set-server=utf8mb4
--collation-server=utf8mb4_general_ci
--explicit_defaults_for_timestamp=true
--lower_case_table_names=1
--max_allowed_packet=128M
--default-authentication-plugin=mysql_native_password
--sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"
--max_connections=3600
volumes:
- ./data:/var/lib/mysql
user: root
第二步 修改master配置(由于docker镜像中可能不存在vim命令) 执行apt-get update,然后再次执行apt-get install vim即可成功安装vim。cd /etc/mysql切换到/etc/mysql目录下,然后我们就可以使用vim编辑my.
文章目录 前情提要Idea 如何反编译一个Jar包 ? 技术点分享instanceof 的翻译基础库的翻译算法实现 区别传参的区别到处乱传的内存管理问题数据初始化类型转换 因为工作需求 需要 将 Jar包 中的代码转换成 C++ 代码。那么这个过程有哪些坑呢? 前情提要 Jar 包 要转成 C++ 程序代码.
第一步 自然是反编译:
工具推荐:Idea 自带的反编译工具.
Idea 如何反编译一个Jar包 ? 导入jar到项目中
左下角的模块列表就能看到了
展开它就能反编译了. 技术点分享 C++ 和 Java太像,毕竟C++是Java的爹.其实转换并不复杂.
只是有些小坑.
instanceof 的翻译 Java中 instanceof 用于判断某个对象 是否是某个类型.
obj instanceof Color 即 如果 obj 是 Color 类型.
那么C++ 怎么翻译呢?
(typeid(*father)中星号是必不可少的.)
使用typeid 并且要解引用.如下例:
Father * father = new Child(); if(typeid(*father) == typeid(Child)){ cout<< "这是一个Child类型" } 基础库的翻译 C++ 的基础类 不支持很多函数.
欢迎关注 “小白玩转Python”,发现更多 “有趣”
使用 NumPy 学习矩阵和求解线性方程组的完整指南
矩阵作为一种数学资源被用于一些现实世界的应用。在本文中,您将使用强大的 NumPy 库学习 Python 中的矩阵,如下所示:
1. 什么是 NumPy,什么时候应该使用它?
2. 使用 NumPy 构造矩阵
3. 矩阵的运算和实例
4. 如何执行矩阵切片
另外:我们还将探讨如何使用 Python 中的矩阵来计算线性方程模型。
让我们从 Python 的矩阵开始。
1. NumPy 是什么,什么时候使用?
NumPy 是一个 Python 库,可以对单个和多维数组和矩阵进行简单的数值计算。顾名思义,NumPy 在数值计算中脱颖而出。许多数据科学库(如 pandas、 scikit-learn 和 SciPy)都依赖 NumPy。它构成了当今 python 编写的数据科学应用程序的一部分。
许多线性代数计算可以很容易地解决 NumPy。在几种机器学习算法中,线性代数是一种重要的数学方法。通过深入了解 NumPy,您可以构建库或扩展现有库以用于机器学习。
提供:
一个强 n 维数组对象,名为ndarray
广播功能
C/C + + 和 Fortran 代码合并工具
生成线性代数,傅里叶变换,和随机数能力
现在让我们进一步了解 Python 矩阵,看看矩阵是如何形成的。
2. 使用 NumPy 构造矩阵
用列表形成一个矩阵
import numpy as np # Create a 2D numpy array with python lists new_array = np.
正是因为软件测试学习和入行的门槛都不是很高,当下也是一个高薪行业,所有有很多伙伴想要加入测试大军。一凡浏览了一些企业大型招聘网站,一般招聘的初级软件测试工程师,要求为两年左右,薪资待遇在7K到11K的样子。我们今天聊的是针对我们大部分人,名校毕业入职大厂,起跑线不一样的不归在此类。
我们直接入真题,对于日常工作来说,作为一名初级测试,做功能测试,俗称点点点。只要掌握从需求分析到上线整个测试流程,以及会编写测试用例。就足矣应付日常工作了,有人带的话一个月时间绝对够了…
下面就来逐个简单聊一下初级测试面试你要掌握的技能,以及日常工作分别有什么用途…
1.测试基础理论: 你要明白一家互联网公司各个岗位是做什么的,主要是前端,后端,产品经理…以及一个版本迭代从需求分析到上线整个测试流程以及使用的管理工具。要掌握测试用例的编写方法与技巧…
2.功能测试: 主要分为app测试,web测试和接口测试。主要就是接口测试,你要学会使用两个工具,一个是postman用来调接口,一个是fiddler用来抓包定位bug。学好接口测试也是为以后的性能压测学习打下基础。
3.数据库: 首学mysql,主要掌握sql语句,增删查改,嵌套子查询,多表查询。加分项会存储过程,懂索引,事务,sql优化。这些初级不强求。工作中使用最多的是查询和修改语句,主要校验前端的传值以及不同系统接口调用数据传输,存值是否正确。
4.linux: 会linux基本命令,比如linux三剑客等,会用命令查日志,会搭建测试环境。因为绝大多数公司服务器以及代码都是部署在linux系统上,工作中用的最多的就是查询日志,定位bug。
5.网络协议: 会http/https协议,高频面试题目接口请求的方式get与post区别,cookie与session机制区别,三次挥手四次断开,输入百度网址发生了什么?这些都要了解。
6.版本控制工具: 主要就是git和svn,git是命令行式,svn是图形化界面,企业主要用来管理代码以及文档等,属于工具使用,比较简单,最好都会。
7.编程语言: java/python之一,初级对编程语言要求不高,不会也可,但是是加分项,最好掌握一些基础语法,比如学完javase,能手写实现冒泡排序或其它排序,很加分。
8.自动化: 主要分为Web自动化,App自动化,接口自动化。初级要求不高,知道一些框架即可,如果学习请优先学习接口自动化,目前需求最多。加分项是会使用搭好的框架编写自动化case,脚本等。
9.性能测试: 初级没要求,加分项会使用jmeter做接口压测,并发测试等
以上罗列的技能基本就是要转行成为一名初级软件测试需要学习掌握的技能,1到6是必学项,决定了企业会不会要你。7到9是加分项,决定了薪水你能谈多高,当然会的技能越多越好,但是至少面试之前把基本的东西请先掌握好,不要浪费面试机会。
如果你
①从事功能测试,想进阶自动化测试
②在测试界混了1、2年,依然不会敲代码
③面试大厂却屡屡碰壁
我邀你进群吧!来吧~~测试员,313782132(Q群里有技术大牛一起交流分享,学习资源的价值取决于你的行动,莫做“收藏家”)获取更多大厂技术、面试资料
如果对python自动化测试、web自动化、接口自动化、移动端自动化、面试经验交流等等感兴趣的测试人,可以关注微信公众号:【伤心的辣条】,获取软件测试工程师大厂面试资料!
最后: 凡事要趁早,特别是技术行业,一定要提升技术功底,丰富自动化项目实战经验,这对于你未来几年职业规划,以及测试技术掌握的深度非常有帮助。
推荐好文: 想转行做软件测试?快来看看你适不适合
关注我不迷茫~
电脑显示不了WiFi的解决方法 亲身经历,并且成功解决
第一种方法: 1. 按住 " win + R ",输入“regedit”按回车键(Enter)运行
2. 找到目录:\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Ndisuio
3. 点一下“Ndisuio”,找到“DisplayName”,双击鼠标左键,弹出的窗口:
如果没有找的“DisplayName”,执行下面,在空白处新建一个
“字符串值”,双击:
改成这样:两处都改
还是这个界面找到“Strar”:
改成这样:
5. 然后单击一下“F5”,进行刷新一下。可以关闭窗口。
6. 按 “Win + R”,输入“cmd”按一下回车键,
输入指令:“netsh winsock reset”按一下回车键
显示这样,重启一下电脑即可。
第二种方法: 准备工具: 1、U盘。
2、身边有一台好的电脑。
看图操作:这是在一台好的电脑上操作的
需要找到:
三个同样的操作单击鼠标右键:
接着看一下U盘是否保存了,这三个文件。
完成保持后关闭窗口。
把这三个文件拷贝到找不到WiFi的电脑,单击运行,弹出窗口,点击“是”,然后重启电脑就好了。
引言 介绍链表之前,先来说一下顺序表,即数组的缺点:
顺序表在存储数据时,不易插入和删除数据;顺序表的存储空间利用率和运行效率都不高;
为了解决上述缺点,线性表可以采用另一种存储结构—链式存储结构。 单链表 定义 (链表没特殊说明默认为单链表)链表是通过一组地址任意的存储单元来存储数据元素的存储结构;这些存储单元可以连续,也可以不连续。
1.单链表结点结构 2.头指针 头指针的作用有两个:
1.标识链表,即链表的名字;
2.存储链表中第一个结点的地址;
3.尾指针 尾指针即链表的最后一个结点,没有后继,因此指针域必须置空,即NULL。
单链表的创建 1.头插法创建单链表 创建步骤:
1.建立头节点Head,另其指针域置空;
2.生成新节点p(申请空间失败的话返回Head);
3.读入数据到p的数据域;
4.将结点p插入到Head之后。
5.重复步骤2~4。
图文表示:
代码实现:
返回值是链表的头节点;
LinkList *CreateLink(){ //头插法 LinkList *head,*p; head=(LinkList *)malloc(sizeof(LinkList));//获得的地址转换为 ListLink *类型 if(head==NULL)return head; head->next=NULL; int x; cin>>x; while(x!=0){ p=(LinkList *)malloc(sizeof(LinkList)); p->data=x; p->next=head->next; head->next=p; cin>>x; } return head; } 2.尾插法创建单链表 尾插法与头插法类似,只是将p结点连入尾结点之后。
代码实现:
LinkList *CreateLink2(){ //尾插法 LinkList *head,*p,*tail; head=(LinkList *)malloc(sizeof(LinkList));//每次申请空间时,严谨的做法是判断申请是否成功 if(head==NULL)return head; head->next=NULL; tail=head; int x; cin>>x; while(x!=0){ p=(LinkList *)malloc(sizeof(LinkList)); p->data=x; tail->next=p; tail=p; tail->next=NULL; cin>>x; } return head; } 单链表的基本操作 1.
参考视频教程
https://www.xin3721.com/eschool/SQLxin3721/
SQL基础教程
一、SQL简介
1:什么是SQL?
A:SQL指结构化查询语句 B:SQL使我们有能力访问数据库 C:SQL是一种ANSI(美国国家标准化组织)的标准计算机语言
2:SQL能做什么?
*面向数据库执行查询 *从数据库中取出数据 *向数据库插入新的记录
*更新数据库中数据 *从数据库删除记录 *创建数据库 *创建表
*创建存储过程 *创建视图 *设置表、存储过程和视图的权限
3:RDBMS
RDBMS是指关系型数据库管理系统
RDBMS是SQL的基础,同样也是所有现代数据库系统的基础,如MS SQL Server、IBM DB2、Oracle、MySQL以及Microsoft Access
RDBMS中的数据存储在被称为表的数据库对象中
表是相关的数据项的集合,他由列和行组成。
二、SQL语法
注意:SQL对大小写不敏感!!!
1:SQL语句后面的分号
某些数据库系统要求在每条SQL命令的末端使用分号。
分号是在数据库系统中分隔每条SQL语句的标准方法,这样就可以在服务器的相同请求中执行一条以上的语句。
如果使用的是MS Access和SQL Server 2000,则不必在每条SQL语句之后使用分号,不过某些数据库要求必须使用分号。
2:SQL DML和DDL
可以把SQL分为两个部分:数据操作语言(DML)和数据库定义语言(DDL)
SQL(结构化查询语句)适用于执行查询的语法。但是SQL语言也包含用于更新、插入和删除记录的语法。查询和更新构成了SQL的DML部分:select、update、delete、insert into 。 数据库定义语言(DDL)部分使我们有能力创建或删除表格,我们也可以定义索引(键),规定表之间的连接,以及事假表间的约束:
Create database、alert database、create table、alert table、drop table、create index、drop index
三、Select
User表里面的数据如下
查询user表里面的user_name字段和user_age字段的所有数据
Select user_name,user_age from user
查询user表中所有的字段数据,用 * 表示列的名称
Select * from user
四、Distinct
Distinct选取所有的值的时候不会出现重复的数据
用普通的查询,查询所有
西门子PLC作为市场占有率非常高的一款PLC,支持Profinet、Profibus、S7、Modbus、TCP等多种通信协议,本案例以S7-1200 PLC为例,主要讲述使用西门子PLC作为ModbusTCP服务器,上位机作为ModbusTCP客户端的应用场景。西门子S7-1200 PLC并不支持直接ModbusTCP,需要编写一些PLC程序,PLC程序的主要目的是通信参数及地址映射的设置。
1、PLC程序编写
2、Modbus地址映射
PLC程序编写完成后,下一步进行Modbus测试,在测试之前,首先明确Modbus地址与PLC地址的映射关系:
由上表可知,Modbus的0区、1区和3区,分别对应PLC的过程映像输出、过程映像输入和过程映像输入,但实际应用中,这三个区应用较少,主要使用的是4区,4区的映射地址是由自己设置,也就是MB_HOLD_REG。
3、通信功能测试
下面我们使用ModbusPoll软件来针对各个区做下简单的测试,具体如下所示:
输出Q点对应0区:该存储区是可读可写的,可以通过ModbusPoll读取到PLC中Q点的值,也可以进行写入,PLC监控及Modbus软件监控结果如下:
输入I点对应1区:该存储区是只读的,可以通过ModbusPoll读取到PLC中I点的值,PLC监控及Modbus软件监控结果如下:
过程输入存储区对应3区:该存储区是只读的,可以通过ModbusPoll读取到PLC中输入存储区的值,PLC监控及Modbus软件监控结果如下:
创建的DB存储区对应4区:该存储区是可读可写的,可以通过ModbusPoll读取到PLC中DB存储区的值,也可以进行写入,PLC监控及Modbus软件监控结果如下:
1.创建一个go文件hello.go
输入以下代码
package main import "fmt" func main(){ fmt.Println("Hello") } 2.切换到该文件所在目录
直接使用go run命令运行
go run hello.go 或
先编译,生成hello的二进制文件,然后通过./hello运行
go build hello.go ./hello
AD的检查和排错
检查active directory是否正常
通过域控制器检查 首先启动域控制器,登录界面如下图,输入密码登录到gaoyk.com域中。
如果正常登录表示我们的域控制器正在工作,但是并不能表明我们的活动目录已经安装完成。所以我们还要在控制器上检查如下几项:
第一项:查看管理工具中相关的项是否已经存在。如下图:
第二项:检查AD数据库文件与SYSVOL文件夹。AD数据库文件会默认安装到:C:\WINDOWS\NTDS文件夹中,其中ntds.dit便是AD的数据库文件,.log文件是日志文件。
而SYSVOL文件夹会默认安装到:C:\WINDOWS\SYSVOL,其中sysvol是共享文件夹。
这个共享文件夹下面还有域文件夹里面还有一个共享文件夹scripts,可以通过net share命令查看共享,如图
第三项:查看DNS服务器内与AD相关的文件夹和SRV记录是否存在或完整,由于域控制器会把自己的主机名,IP地址以及所扮演的角色数据登录到DNS服务器内,以便让其他的计算机通过DNS服务器来寻找这台域控制器。因此必须要检查这些文件夹和SRV记录,打开DNS,如图:
我们发现有一个叫gaoyk.com的正向查找区域,它是安装AD的时候自动创建的,以便让域gaoyk.com中的成员(域控制器,成员服务器,client客户端)将数据登记到这个区域。从上图中我们可以看到主机已经经自己名称以及IP地址登记到这个区域内。同时还有一个_msdcs.gaoyk.com的正向查找区域,因为我们安装活动目录的时候顺便安装了DNS服务器,所以也创建了这个区域,此时server 2019域控制器会将数据登记到_msdcs.gaoyk.com区域内。我们可以浏览这两个区域的_TCP文件夹以及相对应的SRV记录,如图:
从上面这些图中我们可以清晰的看到,域和站点的GC是谁,LDAP服务器是谁,以及KDC服务器是谁。
排错1:如果DNS中没有出现上面这些文件夹以及SRV记录。我们一般需要这么做。首先为域控制器指定正确的DNS服务器的IP地址,然后重新启动Net Logon服务。如果重启Net Logon服务还不正确,请按下面的步骤:1,首先为域控制器指定正确的DNS服务器的IP地址。2,在DNS服务器中建立和域名相同的正向查收区域,并启用动态更新。3,重新启动Net Logon服务。经过这3步相关的文件夹和SRV记录就应该出现了
通过客户端加入域检查 首先我们登录到客户端client,然后对计算机属性进行更改
如果在加入域的时候弹出 错误对话框提示加入域失败,原因可能就是没有给client客户端进行IP的配置。但是这个时候可以利用NETBIOS名来加入域。比如在上面不输入gaoyk.com,而是输入gaoyk,然后点击确定,就会弹出登录对话框,说明通过NETBIOS名我们找到了域控制器,此时使用的是广播。
为了使用域名而不是让NETBIOS名让客户端加入域,我们必须配置client客户端的IP地址。如图:
配置完IP后,我们重新执行刚才的步骤,这次我们就可以顺利的找到域控制器了。我们知道计算机之间的通信是通过IP地址进行的,我们这里输入域名gaoyk.com后,事实上DNS服务器帮我们把gaoyk.com域名解析成域控制器的IP地址。所以客户端加入域需要DNS服务器的支持。此时弹出的登录对话框我们输入管理员账户和密码,点击确定即可加入域。
确定后我们会被提示许哟啊重启,重启后我们发现界面已经更改
当选择登录到域时,我们还必须在域控制器上位这个客户端创建一个用户账户。
此时我们打开计算机的管理会发现computers中已经多了一台client1,如图
现在我们来创建一个用户账户
密码默认要符合复杂度定义条件,A-Z,a-z,0-9,特殊字符等任选三种,同时长度必须大于等于7位。可以选择密码永不过期,这样可以解除默认42天的限制。
然后我们发现张三这个用户账户已经成功创建
然后我们可以用此账户进行登录
这时我们发现和原先的桌面不一样了
这篇文章只是纯粹分析python pyc文件格式,主要是关于pyc在文件中的存储方式进行了解析。pyc是python字节码在文件中存储的方式,而在虚拟机运行时环境中对应PyCodeObject对象。关于PyFrameObject以及PyFunctionObject等运行时结构,后续希望学习透彻了能够一并分析。
1.示例文件
源文件test.py
s = "hello"
def func():
a = 3
print s
func()
通过执行python pyc_generator.py test 可以生成编译好的pyc文件。
##pyc_generator.py
import imp
import sys
def generate_pyc(name):
fp, pathname, description = imp.find_module(name)
try:
imp.load_module(name, fp, pathname, description)
finally:
if fp:
fp.close()
if __name__ == "__main__":
generate_pyc(sys.argv[1])
得到test.pyc后,执行hexdump -C test.pyc可以得到如下二进制字符流。
00000000 03 f3 0d 0a f6 e9 38 55 63 00 00 00 00 00 00 00 |......8Uc.......|
00000010 00 01 00 00 00 40 00 00 00 73 1a 00 00 00 64 00 |.
下面盛泰鼎盛给大家讲讲计算机软考各科目考试内容
软考初级:
程序员:计算机相关基础知识;基本数据结构和常用算法;C程序设计语言以及C++。Java中的一种程序设计语言。
网络管理员:计算机系统、网络操作系统、数据通信的基础知识;计算机网络的相关知识;以太网的性能、特点、组网方法及简单管理;主流操作系统的安装、设置和管理方法;Web网站的建立、管理与维护方法;交换机和路由器的基本配置。
信息技术处理员:信息技术的基本概念;计算机的组成、各主要部件的功能和性能指标;操作系统和文件管理的基本概念和基本操作;文字处理、电子表格、演示文稿和数据库应用的基本知识和基本操作;Internet及其常用软件的基本操作。
信息系统远行管理员:计算机系统的组成及主要设备的基本性能指标;操作系统、数据库系统、计算机网络的基础知识;多媒体设备、电子办公设备的安装、配置和使用;信息处理基本操作;信息化及信息系统开发的基本知识。
软考中级:
软件评测师:操作系统、数据库、中间件、程序设计语言、计算机网络基础知识;软件工程知识;软件质量及软件质量管理基础知识;软件测试标准、测试技术及方法;软件测试项目管理知识。
软件设计师:计算机相关基础知识;常用数据结构和常用算法;C程序设计语言,以及C++、Java中的一种程序设计语言;软件工程、软件过程改进和软件开发项目管理的基础知识;软件设计的方法和技术。
网络工程师:计算机系统、网络操作系统、数据通信的基础知识;计算机网络的相关知识,包括计算机网络体系结构的网络协议、计算机网络互联技术、网络管理的基本原理和操作方法、网络安全机制和安全协议;网络系统的性能测试和优化技术,以及可靠性设计技术;网络新技术及其发展趋势。
多媒体应用设计师:多媒体计算机的系统结构;多媒体数据获取、处理及输出技术;多媒体数据压缩编码及其适用的国际标准;多媒体应用系统的创作过程,报考数字音频编辑、图形的绘制、动画和视频的制作、多媒体制作工具的使用等。
嵌入式系统设计师:嵌入式系统的硬软件基础知识;嵌入式系统需求分析方法;嵌入式系统设计与开发的方法及步骤;嵌入式系统实施、运行、维护知识;软件过程改进和软件开发项目管理等软件工程基础知识;系统的安全性、可靠性、信息技术标准以及有观法律法规的基本知识。
电子商务设计师:电子商务基本模式、模式创新及发展趋势;电子商务交易的一般流程;电子支付概念理想的物流技术和供应链技术;电子商务网站的运用、维护、和管理;电子商务相关的经济学和管理学基本原理、法律法规等。
系统集成项目管理师:信息系统集成项目管理知识、方法和工具;系统集成项目管理工程师职业道德要求;信息化知识;信息安全知识与安全管理体系。
信息系统监理师:信息系统工程师监理知识、方法和工具;信息系统工程监理师的职业道德要求;信息系统工程监理的有关政策、法律、法规、标准和规范。
数据库系统工程师:数据库系统基本概念及关系理论;常用的大型数据库管理系统的应用技术;数据库应用系统的设计方法和开发过程;数据库系统的管理和维护方法。
信息系统管理工程师:信息化和信息系统集成知识;信息系统开发的基础过程与方法;信息系统管理维护的知识、工具与方法。
信息安全工程师:信息安全的基本知识;密码学的基础知识与应用技术;计算机安全防护与检测技术;网络安全防护与处理技术;数字水印在版权保护中的应用技术;信息安全相关的法律法规和管理规定。
软考高级:
信息系统项目管理师:信息系统项目管理知识和方法;项目整体绩效评估方法;常用项目管理工具;信息系统相关法律法规、技术标准与规范。
系统分析师:信息系统开发所需的综合技术知识,包括硬件、软件、网络、数据库等;信息系统开发过程和方法;信息系统开发标准;信息安全的相关知识与技术。
系统架构设计师:计算机硬软件知识;信息系统开发过程和开发标准;主流的中间件和应用服务器平台;软件系统建模和系统架构设计基本技术;计算机安全技术、安全策略、安全管理知识。
网络规划设计师:数据通信、计算机网络、计算机系统的基本原理;网络计算环境与网络应用;各类网络产品及其应用规范;网络安全和信息安全技术、安全产品及其应用规范;应用项目管理的方法和工具实施网络工程项目。
系统规划与管理师:IT战略规划知识;信息技术服务知识;IT服务规划设计、部署实施、运营管理、持续改进、监督管理、服务营销;团队建设与管理的方法和技术;标准化相关知识。
有时候一些网站会将视频文件转换为一大堆的.ts,如图,想下载几乎不可能。现在介绍一种完美的解决方案。
1.材料准备: ①Chrome浏览器
②VLC视频播放器
③猫抓插件
插件安装过程参考
2.m3u8文件抓取 点击猫抓图标
点击这个,复制m3u8文件地址(有两个一般是清晰度不同的问题,两个都可以)
3.打开神器VLC media player 打开网络串流
然后
粘贴刚才的地址并选择串流
然后
下一步
然后
添加保存位置
然后
不要激活转码
不要串联所有基本流
然后就是就这样了,等进度条走完就下载完了
然后转换完了之后,把VLC的窗口关掉,否则保存的文件打不开,这样就把所有的.ts文件下载下来并全自动地合并为了一个文件。
Python DataFrame 设置输出不显示index(索引)值的方法
在输出代码行中,加入“index=False”如下:
m_pred_survived.to_csv("clasified.csv",index=False)
以上这篇Python DataFrame 设置输出不显示index(索引)值的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。
时间: 2018-06-07
前言 最近在网上搜了许多关于pandas.DataFrame的操作说明,都是一些基础的操作,但是这些操作组合起来还是比较费时间去正确操作DataFrame,花了我挺长时间去调整BUG的.我在这里做一些总结,方便你我他.感兴趣的朋友们一起来看看吧. 一.创建DataFrame的简单操作: 1.根据字典创造: In [1]: import pandas as pd In [3]: aa={'one':[1,2,3],'two':[2,3,4],'three':[3,4,5]} In [4]: bb=
index()方法确定字符串str,如果起始索引beg和结束索引end在末尾给出了找到字符串或字符串的一个子串.这个方法与find()方法一样,只是如果没有找到子符趾会抛出一个异常. 语法 以下是index()方法的语法: str.index(str, beg=0 end=len(string)) 参数 str -- 此选项指定要搜索的字符串. beg -- 这是开始索引,默认情况下是 0. end -- 这是结束索引,默认情况下它等于该字符串的长度. 返回值 方法返回索引,如果找到这个str:
pandas提供了set_index方法可以将DataFrame的列(多列)变成行索引,通过reset_index方法可以将层次化索引的级别会被转移到列里面. 1.DataFrame的set_index方法 data = pd.DataFrame(np.arange(1,10).reshape(3,3),index=["a","b","c"],columns=["A","B","C"])
reindex更多的不是修改pandas对象的索引,而只是修改索引的顺序,如果修改的索引不存在就会使用默认的None代替此行.且不会修改原数组,要修改需要使用赋值语句. series.reindex() import pandas as pd import numpy as np obj = pd.Series(range(4), index=['d', 'b', 'a', 'c']) print obj d 0 b 1 a 2 c 3 dtype: int64 print obj.
在用VMware虚拟机的时候,有时会发现打开虚拟机时提示“该虚拟机似乎正在使用中。如果该虚拟机未在使用,请按“获取所有权(T)”按钮获取它的所有权。否则,请按“取消(C)”按钮以防损坏。配置文件: D:win10x64Windows 10 x64.vmx。”这是由于虚拟机未正常关闭引起的。 我们首先点击“获取所有权(T)”按钮,会发现弹出一个窗口,显示“ 无法打开虚拟机: D:win10x64Windows 10 x64.vmx获取该虚拟机的所有权失败。主机上的某个应用程序正在使用该虚拟机。配置文件: D:win10x64Windows 10 x64.vmx。”等信息。这说明获取所有权失败了。 当点击“取消(C)”按钮是直接退出窗口,什么也不弹出。这时发现不管点那个按钮都不能解决问题。 进入到存放此台Vmware虚拟机虚拟磁盘文件及配置文件存放的位置(也就是弹出提示窗口上的路径),在这里是D:win10x64这个目录下,找到后缀为.lck文件夹。 然后,将后缀为.lck的文件夹删除,或者或避免删错可以移动到备份文件夹中,也可以直接重命名此文件夹,在这里我将文件夹Windows 10 x64.vmx.lck改为Windows 10 x64.vmx.lck.backup。 然后重新打开虚拟机,发现此虚拟机可以正常打开了,这样就成功的解决了“该虚拟机似乎正在使用中”问题。
这是实现出来的效果 通过点击加号减号或是文件夹可实现树的收放
下面先将下它的原理 首先看看如何实现点击加号减号完成切换
<div class="checkbox">
<input type="file" id="handsome" /><label for="file">文件夹</label>
</div>
这是我们的html结构 我们是通过checkbox 和 label来实现这个效果的
checkbox通过css input:checked来检查状态
label设置样式
css
.checkbox input{
cursor:default;
opacity: 0;
}
.checkbox label{
cursor: pointer;
}
.checkbox input+label{
background: url(toggle-small-expand.png) no-repeat;
padding-left: 20px;
}
.checkbox input:checked + label{
background: url(toggle-small.png) no-repeat; }
我们将图标设置在label上 然后将input框通过透明度消失掉 把图标移动到input框
当我们点击这个图标时其实就把选择框选中了 自然input:checked也就选择到了它
原理并不难,但实现的效果是挺不错的
下面我把代码贴上 讲解都在注释里
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>纯css树</title>
<style>
.tree{
margin-top: 40px;
padding-left: 10px; /*本来默认是40px*/
match() 方法将检索字符串 stringObject,以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。
如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。除了这些常规的数组元素之外,返回的数组还含有两个对象属性。index 属性声明的是匹配文本的起始字符在 stringObject 中的位置,input 属性声明的是对 stringObject 的引用。
如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到 stringObject 中的所有匹配子字符串。若没有找到任何匹配的子串,则返回 null。如果找到了一个或多个匹配子串,则返回一个数组。不过全局匹配返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。
摘自w3c教程
str 的值改成 /HELLO hello/
我正在处理一个使用python和arcpy的脚本来处理Landsat卫星图像。在脚本的末尾,每次都在同一位置得到一个错误。在一次成功运行代码后发生错误(即在第二次出现相同任务时发生错误)
print "Starting Rt_B2dpy (2 of 4)"
if arcpy.Exists(Rt_B2dpy):
arcpy.Delete_management(Rt_B2dpy)
Rt_B2dpy = Rt2 - 1
Rt_B2dpy.save("Rt_B2dpy")
print "Rt_B2dpy has been created"
我将env.overwriteOutput设置为True,这不是问题所在。
我将此代码交给朋友运行,他们让它处理这段代码的所有4次出现,但是他们的输出是空白的。我还在那里使用了修改过的脚本(更改了一些路径条目),并在与第一个相同的位置得到了这个错误:
exceptions.EOFError:[Errno 10054]远程主机强行关闭现有连接
此错误导致python和编辑器崩溃。
该脚本为第一次运行生成网格,但第二次运行会创建一个在ArcGIS中无法读取的网格。
我在一台带有8 GB RAM的Mac上的Windows虚拟机(parallels)上工作。虚拟机使用4 GB的RAM。
我不知道发生了什么或如何调试它!任何帮助将不胜感激。
替代方法=我通过将输出保存为TIF图像而不是光栅文件找到了解决方法。
Tuple 是不可变 list。 一旦创建了一个 tuple 就不能以任何方式改变它。
Tuple 与 list 的相同之处
定义 tuple 与定义 list 的方式相同, 除了整个元素集是用小括号包围的而不是方括号。
Tuple 的元素与 list 一样按定义的次序进行排序。 Tuples 的索引与 list 一样从 0 开始, 所以一个非空 tuple 的第一个元素总是 t[0]。
负数索引与 list 一样从 tuple 的尾部开始计数。
与 list 一样分片 (slice) 也可以使用。注意当分割一个 list 时, 会得到一个新的 list ;当分割一个 tuple 时, 会得到一个新的 tuple。
Tuple 不存在的方法
您不能向 tuple 增加元素。Tuple 没有 append 或 extend 方法。
您不能从 tuple 删除元素。Tuple 没有 remove 或 pop 方法。
您不能在 tuple 中查找元素。Tuple 没有 index 方法。
概述 今天主要分享下怎么用Python实现斐波那契数列,大家有空可以玩一下~
需求 用Python脚本实现斐波那契数列。
思路 斐波那契数列,也称兔子数列,是指1,1,2,3,5,8,13,21,34,55,89,144......这样一个数列,在这个数列当中,从第三项起,每一项都是前两项数字之和。如果图方便就递归实现,图性能就用循环。
非递归实现打印斐波那契数列 #usr/bin/python## 斐波那契数列,也称兔子数列,是指1,1,2,3,5,8,13,21,34,55,89,144......这样一个数列,# 在这个数列当中,从第三项起,每一项都是前两项数字之和。i=0a=1b=1#a,b=b,a+b代表交换,while循环中,这里让程序打印了前24项。while i<24: print(a) a,b=b,a+b i+=1 输出:
方法一: 递归实现 #usr/bin/python# 斐波那契数列,也称兔子数列,是指1,1,2,3,5,8,13,21,34,55,89,144......这样一个数列,# 在这个数列当中,从第三项起,每一项都是前两项数字之和。def Fib(n):return 1 if n<=2 else Fib(n-1)+Fib(n-2)print(Fib(int(input('递归实现打印斐波那契数列第N项:')))) 方法二:朴素实现 #usr/bin/python# 斐波那契数列,也称兔子数列,是指1,1,2,3,5,8,13,21,34,55,89,144......这样一个数列,# 在这个数列当中,从第三项起,每一项都是前两项数字之和。target=int(input('朴素实现打印斐波那契数列第N项:'))res=0a,b=1,1for i in range(target-1): a,b=b,a+bprint(a) 结果:
觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~
参考视频:https://www.bilibili.com/video/BV1aC4y1p7bF/?p=5
参考文档:https://www.cnblogs.com/myitnews/p/12364455.html#autoid-4-0-0
事务开启 数据库会开启行锁
编程式事务 DataSouceTransactionManager(数据源事务管理器)
主要api:开启事务,提交事务,回滚事务
声明式事务 @transaction 编程式事务封装+AOP动态代理实现
常用属性:rollbackFor 默认捕获到error和runtimeException 会回滚
手动回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
(手动回滚执行不会中断代码,代码继续往下走,回滚已经执行的sql)
radians()方法把角度转化为弧度角x。
语法
以下是radians()方法的语法:
radians(x)
注意:此函数是无法直接访问的,所以我们需要导入math模块,然后需要用math的静态对象来调用这个函数。
参数
x -- 这必须是一个数值。
返回值
此方法返回一个角度的弧度值。
例子
下面的示例演示radians()方法的使用。
#!/usr/bin/python
import math
print "radians(3) : ", math.radians(3)
print "radians(-3) : ", math.radians(-3)
print "radians(0) : ", math.radians(0)
print "radians(math.pi) : ", math.radians(math.pi)
print "radians(math.pi/2) : ", math.radians(math.pi/2)
print "radians(math.pi/4) : ", math.radians(math.pi/4)
当我们运行上面的程序,它会产生以下结果:
radians(3) : 0.0523598775598
radians(-3) : -0.0523598775598
radians(0) : 0.0
radians(math.pi) : 0.0548311355616
radians(math.pi/2) : 0.0274155677808
radians(math.pi/4) : 0.0137077838904
本文标题: Python中转换角度为弧度的radians()方法
本文地址: http://www.cppcns.com/jiaoben/python/124859.html
#include "ESP8266.h" #include "dht11.h" #include "SoftwareSerial.h" #define SSID "540ND" #define PASSWORD "" #define HOST_NAME "api.heclouds.com" #define DEVICE_ID "" #define HOST_PORT (80) String APIKey = " "; #define INTERVAL_SENSOR 5000 dht11 DHT11; #define DHT11PIN 4 SoftwareSerial mySerial(3, 2); ESP8266 wifi(mySerial); void setup() { mySerial.begin(115200); Serial.begin(9600); Serial.print("setup begin\r\n"); Serial.print("FW Version: "); Serial.println(wifi.getVersion().c_str()); if (wifi.setOprToStation()) { Serial.print("to station ok\r\n"); } else { Serial.print("to station err\r\n"); } if (wifi.joinAP(SSID, PASSWORD)) { Serial.print("Join AP success\r\n"
张俊红 | 作者
俊红的数据分析之路 | 来源
方差分析有一个很重要的前提就是叫方差齐性。这一篇来讲讲如何来检验方差齐性。
先讲讲什么是方差齐性,方差齐性是指不同组间的总体方差是一样的。那为什么方差分析的前提是要组间的总体方差保持一致呢?先想想方差分析是做什么呢?方差分析是用来比较多组之间均值是否存在显著差异。那如果方差不一致,也就意味着值的波动程度是不一样的,如果此时均值之间存在显著差异,不能够说明一定是不同组间处理带来的,有可能是大方差带来大的波动;如果方差一样,也就意味着值的波动程度是一样的,在相同波动程度下,直接去比较均值,如果均值之间存在显著差异,那么可以认为是不同组间处理带来的。
方差齐性检验是对两组样本的方差是否相同进行检验。检验思想与均值之间差异性检验是一样的。常用的方法有:方差比、Hartley检验、Levene检验、BF法、Bartlett检验。
1
方差比
方差比顾名思义就是两组方差的比,用较大一组的方差除较小一组的方差,最后得到一个F值,然后根据F值的大小来判断两组之间的方差是否相等。F值越大,则认为两组方差越不相等。
2
Hartley检验
Hartley检验与方差比的思想比较类似,差别在于Hartley检验用于多组方差的检验,用多组中最大的方差除最小的方差,得到一个F值,然后通过F值的判断来对方差齐性进行判断。
3
Levene检验
Levene检验是将每个值先转换为为该值与其组内均值的偏离程度,然后再用转换后的偏离程度去做方差分析,即组间方差/组内方差。
在这里关于组内均值有多种计算方式:平均数、中位数、截取平均数(去掉最大和最小值后求平均)。
在Python中有现成的函数可以使用:
from scipy.stats import levene stat, p = levene(x, y, z) print(stat, p) 上面公式中x、y、z代表不同组的样本。
4
BF法
Levene检验最开始计算组内均值的时候只是用了组内平均数,后来又有名叫Brown和Forsythe的两位前辈对齐进行了改造,添加了中位数和截取均值的方法,简称BF法。
这个在Python里面用的也是levene函数,通过调整参数的取值即可。
5
Bartlett检验
Bartlett检验的核心思想是通过求取不同组之间的卡方统计量,然后根据卡方统计量的值来判断组间方差是否相等。该方法极度依赖于数据是正态分布,如果数据非正态分布,则的出来的结果偏差很大。
在Python中有现成的函数可以使用:
from scipy.stats import bartlett stat, p = bartlett(x, y, z) print(stat, p) 上面公式中x、y、z代表不同组的样本。
6
总结
前面介绍了好几种方法,最后来总结下这几种方法的利弊及适用条件:方差比、Hartley检验、Bartlett检验都需要原始数据是正态分布,Levene检验和BF法对正态分布不是很依赖。比较常用的是Levene检验,适用于多组方差的比较,且对正态性没要求。
●可以从一份超市数据集中分析出啥?
●10大Python数据可视化库!
后台回复“入群”即可加入小z数据干货交流群
Spring中自定义权限注解 实现功能:
在方法上加上注解@PreAuth(“xxx”), 根据xxx不同内容,可以判断当前请求是否有访问该接口的权限,如果有则放行,反之则返回无权限.
其中@PreAuth(“xxx”)中 “xxx” 可以填写角色或者资源等来校验(xxx是个表达式,解析后,然后调用不同的方法去执行返回布尔值)
1. 自定义注解 import java.lang.annotation.*; /** * 权限注解 用于检查权限 规定访问权限 * * @author Chill * @example @PreAuth("#userVO.id<10") * @example @PreAuth("hasRole(#test, #test1)") * @example @PreAuth("hasPermission(#test) and @PreAuth.hasPermission(#test)") */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Inherited @Documented public @interface PreAuth { String value(); } 2. 编写处理@PreAuth(“xxx”)中处理"xxx"的方法 /** * 权限判断 * * @author Chill */ public class AuthFun { /** * 权限校验处理器 */ private static IPermissionHandler permissionHandler; private static IPermissionHandler getPermissionHandler() { if (permissionHandler == null) { permissionHandler = SpringUtil.
注释
单行注释:用#
快捷键Ctrl+/
取消注释快捷键Ctrl+/
多行注释:
两种方式(英文单引号或双引号):
"""说明的文字""" 或者 '''说明的文字'''
变量和变量类型
变量:用来临时保存数据的,如下,num1、num2、ret都是变量
num1 = 10# 第一次输入一个10
num2 = 20# 第二次输入一个20
ret = num1 + num2# 后来输出结果为30
print(ret)# 输出结果
变量类型
Numbers(数字):
int:有符号类型
long:长整型(也可代表八进制和十六进制),
float:浮点型
complex:复数,
Bool布尔值类型:
True:代表正确
False:代表错误
String(字符串)常用
List(列表)
Tuple(元组)
Dictionary(字典)
掌握int、float、bool、str
字符串 "文字或者字符或者字符" 还可以 '文字或者字符或者字符'
查看一个变量的类型type(),如下
print(type(name))
运行后结果:
标识符命名规则(标识符由字母、下划线和数字组成,且数字不能开头),标识符区分大小写
小驼峰式命名法(lower camel case): 第一个单词以小写字母开始;第二个单词的首字母大写,例如:myName、aDog
大驼峰式命名法(upper camel case): 每一个单字的首字母都采用大写字母,例如:FirstName、LastName
还有一种命名法是用下划线“_”来连接所有的单词,比如send_buf,
标识符的规则(变量名 函数名 类型 模块名)
定义一个变量 名字
小驼峰
myNameIs = "小明"
定义一个变量 年龄
VM598 WAService.js:2 (in promise) MiniProgramError {“errMsg”:“redirectTo:fail can not redirectTo a tabbar page”} Object 微信小程序出现的页面跳转错误
解决方法 wx.redirectTo({ url: '../index/index', }) 更改为
wx.switchTab({ url:'../index/index' }) 原因:如果是tabbar页面就别用redirectTo,tabbar页面只能用switchTab。
参考:http://sanshu.cn/article/14051.html
路由算法与路由协议概述
路由算法的分类
分层次的路由选择协议 采用的原因:
Ip数据报格式 Ip数据报的分片 最大传送单元MTU:链路层数据帧可封装数据的上限,以太网的MTU是1500字节
IPv4地址 ARP协议 三种路由协议比较
我在用PyCharm。我在以下位置有一个python脚本:
C:\Users\XYZ\PycharmProjects\Project1\playground.py
playground.py只有一行代码,如下所示import PyTbl
在“Project1”文件夹中还有另一个文件:
C: \Users\XYZ\PycharmProjects\Project1\PyTbl.pyd
运行python script playground.py时,出现以下错误:ImportError: numpy.core.multiarray failed to import
Traceback (most recent call last):
File "C:/Users/XYZ/PycharmProjects/Project1/playground.py", line 1, in import PyTbl
SystemError: initialization of PyTbl raised unreported exception
如果我将鼠标悬停在PyCharm编辑器中playground.py中的python代码行上,会收到以下错误消息:
“没有名为PyTbl的模块”
知道如何将.pyd文件导入到python脚本中吗?
无论你是备考408,还是912,亦或只是一个单纯的操作系统爱好者,我们都会在各种操作系统的教材上看到这么一句表达:操作系统是管理计算机硬件和软件资源的计算机程序。可是,操作系统究竟是如何工作的呢?中断的具体过程又是什么样的?对于很多读者来说,你可能已经学习了很多进程调度算法、地址虚拟化算法、文件系统特征等,但是对于这些最基本的问题,你可能依然感觉隔着一层朦胧的纱。今天,我们就能揭开这层神秘面纱,看一下一些操作系统最基本的问题。 在谈操作系统之前,我们必须先大致描述一些硬件知识,我们必须知道哪些事情是硬件来做的。在我们的CPU中,有这么一些引脚,它为CPU传递中断信号。这里,我们提及了一个大家都很熟悉的名词”中断“,没错,中断,它并不是操作系统规定出来的概念,而是一台计算机刚被造出来,就被赋予的硬件功能。那么我们来看看,中断发生的时候,硬件又会进行哪些工作呢? 中断的触发原因多种多样,比如鼠标或键盘所引发的”外部中断“,运算器在执行触发运算时发现除数为0,还有应用程序使用的”系统调用“等。而每一类中断,都是硬件计划好的,每一种中断都有一个中断号(指向中断向量),请记住,某种中断提供给CPU哪一个中断号,是硬件决定的,而不是操作系统。 在x86下,CPU收到了引脚传来的中断号后,它会做什么呢?它会查看我们内存中的IDT表,而这个表的基址存储在一个叫做IDTR的寄存器中,而查看表里的哪一项则取决于我们的中断号,与此同时,CPU进入内核态。例如,如果中断原因为除数为0,它便会给我们一个0中断号,我们便取出了IDT表中的第0项。取出IDT表项后,其中含有中断服务程序的段基址和段内偏移,依据这两个信息,我们便可以寻找到中断服务程序的具体地址,执行中断服务程序了。所以,我们经常会看到这样的论述:”中断向量地址是中断服务例程的地址的地址“。 但是要完整执行一个中断,只找到中断服务程序显然无法做到,因为我们还需要传入参数。例如我们需要读一个内存,那么只告诉CPU我们需要一个系统调用是远远不够的,因为内核要完成它还需要知道其他信息:例如对应的系统调用号(注意区分系统调用号与中断号,所有的系统调用都是同一个中断号进入同一个中断服务程序,根据系统调用号来决定具体执行哪一个系统调用)、要读的内存地址、缓冲区地址等。由于陷入内核态后会产生堆栈和虚拟空间的切换,所以我们能够用来传递这些信息的只有寄存器。这个时候,我们只需要做好一个约定 ,例如,系统调用执行前,我们把系统调用号压入到AX寄存器中,并且和内存约定好从AX中取走系统调用号,就可以完成系统调用号的跨特权级传递。 所以,在这个过程中,哪些工作是由操作系统来做的呢?我们可以看到,CPU会根据中断去查IDT,但是IDT中的内容却是由我们的os来填写的,也就是说操作系统可以决定每一类中断需要跳转到哪里去执行中断服务程序,也可以决定中断服务程序的具体内容,也就是规定每一类中断后计算机所要进行的行为。与此同时,信息如何传递的具体约定也是由系统程序员来决定的。 为什么要说这么多中断的内容?因为,中断是操作系统工作的基石。我们的操作系统在完成初始的配置之后,便开始进入一种空转的状态,它等待着响应各种各样的中断。所以,可以说,操作系统程序其实是一个很被动的存在,只有发生中断时它才会跳出来执行”管理者”的功能。所以,操作系统其实是中断响应的。 理解了上述过程,我们便理解了操作系统运行的一些最基本的逻辑,也能够更充分的理解教材中一些看起来很莫名其妙的表达。以上表达,均基于ucore操作系统和x86,符合408和912考察的操作系统的特征,可能与现代操作系统的特点有所偏差,希望有更高要求的读者能够理解。
而今天的文章,我们就来一起基于 Python ,配合颜色与字体的选择搭配,使用简短的代码,就可以创作出艺术海报级别的 山脊地图 。
2 基于ridge_map的山脊地图绘制
我们主要使用 matplotlib 与 ridge_map 来完成一幅山脊图的创作,使用 pip install ridge_map 完成对 ridge_map 的安装之后,我们先一个非常简单的例子开始:
from ridge_map import RidgeMap
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt
# 从本地的字体文件中注册字体
font_prop = fm.FontProperties(fname="fonts/UncialAntiqua-Regular.ttf")
# 基于传入的区域左下角、右上角经纬度
# 来获取原始高程数据并绘制成山脊地图
# 如果你有“特殊的上网技巧”,这一步等待时间会很短
RidgeMap(bbox=(-156.250305,18.890695,-154.714966,20.275080),
font=font_prop)
.plot_map(label="Hawai'i")
plt.savefig('图3.png')
图3
这就是 ridge_map 绘制山脊地图的基本模式,利用 matplotlib.font_manager 注册要使用的字体,再将绘图区域bbox信息与字体属性传入 RidgeMap() 之后调用 plot_map() 方法即可进行绘制。
但如果你想要制作出像下面这种更多定制内容的山脊地图,就需要了解多一些知识:
图4
下面我们分部分来展开介绍:
2.1 数据准备
我们统一使用 RidgeMap 接受 bbox 参数确定区域范围,格式为 (左下角经度, 左下角纬度, 右上角经度, 右上角纬度) ,其基于的高程数据来自 NASA 的 SRTM 数据集,分辨率为1弧秒(约30米),适用于北纬60°到南纬60°之间的区域。
作者丨黄澄楷
研究方向丨多媒体信息检索/内容理解
本文是发表在 MM18 上的一篇跨模态检索文章,作者提出了一种采用综合保持距离的自编码器(CDPAE)的新颖方法,用以解决无监督的跨模态检索任务。
之前的无监督方法大部分使用属于相同对象的跨模态空间的成对表示距离进行度量学习。但是,除了成对距离之外,作者还考虑了从跨媒体空间提取的异构表示距离,以及从属于不同对象的单个媒体空间提取的齐次表示距离,从而达到了更高的检索精度。
研究动机 虽然先前的无监督跨模态检索方法已经有了不错的表现,但是仍然有两个问题叩待解决,第一,如何减少特征中冗余的噪声的负面影响。
▲ 背景中的SIFT特征会影响Cat图像的检索 第二,如何直接使用不同对象的表示(representation)来表达它们之间的关系(relationship)。
即在大多数非监督方法中,不考虑虚线的关系。这两个问题在无监督跨模态检索的研究中涉及的较少。
研究方法 上图就是作者提出的 CDPAE 的框架结构图,总体上看,CDPAE 包含四个并行的去噪编码器,并定义了综合的保距公共空间,其中根据输入保留三种距离,然后使用联合损失函数将自编码器的重构损失和相关损失结合起来。最后,还提出了一种无监督跨模态相似度的度量方法。 具体来看,CDPAE 包含四个部分:去噪编码器、综合保距空间、联合损失函数和无监督跨模态相似度测量,由于数据集的限制,本文与大部分其他跨模态检索任务一样,只进行图文互搜的实验。接下来分别对每个部分进行介绍。
1. CDPAE 的第一部分由四个去噪编码器组成,其中两个提取图像相关的特征,另外两个与文本特征相关,去噪的自编码器负责相同的模态,它们共享相同的参数,因此相同模态的表示也具有相同的转换。
在具体的训练迭代中,从两个对象中提取的两种模式之间的四种表示形式用作输入。如:图中海鸥图、描述海鸥图的文本、自行车图、描述自行车的文本作为输入。 在去噪自动编码器中,将固定数量的输入分量随机设置为零,其余的保持不变。该方法模拟了从输入端去除冗余噪声的过程;因此,它减少了冗余噪声的负面影响。此外,归零过程可以看作是一种数据扩充的过程,它加强了从不同模态中提取的表示中局部结构之间的联系。
去噪自编码器的重构损失定义为:
V={v} 代表的是图像的数据集,T={t} 代表的是对应的文本数据集,根据之前提到的输入方法,使用自编码器从提取两组来自两个对象对应的特征(图像文本对特征),(vi,ti)-->(海鸥图的图像特征和文本特征)和 (vj,tj)-->(自行车的图像特征和文本特征),av,wv,θv 表达的是图像自编码器的参数,at,wt,θt 代表的是文本自编码器的参数,Z(*) 是随机置零过程,F(*) 是编码过程,G(*) 是解码过程。 2. 第二部分是综合保距空间的构造:CDPAE 使用余弦距离来测量相同模态空间中的特征相似性。测量的公式:
在综合保距空间中有三种距离:成对距离、异质距离、齐次距离,分别给出定义:
a. 成对距离的损失:
就是其他无监督跨模态检索都考虑的距离。其中 D 为:
这个距离的作用是:成对的距离会导致公共空间,其中属于相同对象的不同模态的表示会聚在一起(海鸥的图像文本聚在一起、自行车的图像文本聚在一起)。
b. 异质距离的损失:
反映了不同对象在不同模态中的表示之间的关系,这里度量的时候限制它们与原始模态空间相对应的对象之间的距离一致。
c. 齐次距离的损失:
齐次距离反映的是同一模态下来自不同对象的表示之间的关系,因为每次迭代中,都计算相同两个对象之间的异质与齐次距离,所以设置它们的值相同。
所以综合的保距空间如下:
3. 然后又使用了一种联合损失函数,同时计算去噪自编码器的重构损失和综合保距公共空间的相关损失:
4. 最后作者又提出了一种新型的无监督跨模态相似度度量方法,在公共空间中,训练数据集中变换后的特征之间的距离通常会比测试数据中的距离更具有可信度。
所以讲两个特征之间的相似性定义为基于 KNN 分类器的边缘概率,该分类器用于对训练样本中的每个模态的表示进行分类,两种表示的相似性可以定义为:
注意:这里的 pi/qj 分别是图像模态/文本模态的 top k 近邻样本(这里的 top k 近邻样本不区分模态)。同时,假设两个表示之间的距离反映了它们属于同一语义范畴的可能性,因此,如果训练数据集中的两种表示形式成对对应的话,它的可能性就是 1,否则:
D 采用的是余弦相似距离,取值范围是 0~1,距离越小,对应的表示属于同一类别可能性就越大,进一步,去定义一个测试样本表示与其 k 个最近的训练数据属于同一个类别的条件概率为:
在开发过程中,经常会用到字符串来存储字符内容。在其他编程语言中用成对双引号" "声明字符串,用成对单引号' '声明单个字符,而Python没有这种区别,它无论单个或多个字符都用字符串表示。
字符串除了普通的内容,还有转义和原生。为了方便操作,Python提供了很多函数。
6.1 声明 Python可用单个双引号"或单引号',也可以用三个双引号"""或单引号'''声明字符串。推荐使用双引号。
细心的你,不知注意到没?--三个双引号或单引号,不是注释用的吗?怎么字符串也用这个。是的,把内容赋值给变量时,就表示字符串。
# 用单个双引号a = "双引号"print(a, type(a))# 用单个单引号b = '单引号'print(b, type(b))# 用三个双引号c = """三个双引号"""print(c, type(c))# 用三个单引号d = '''三个单引号'''print(d, type(d)) 6.2 转义 有些符号,如双引号"、单引号',本身已有特殊含义,如要输出它们,就需要进行转义处理。Python跟其他编程语言一样,也是用反斜杠来进行的。
# 用进行换行
i = "第1行,第2行。"
print(i)
# 用"输出双引号
say = "我说:""
print(say)
如果转义内容用的比较多时,样子会很难看,工作量也大了一些,当需要多个反斜杠转义时,则使用原始字符r或R。
# 用r表示原始内容path = r"c:softwareowest"print(path) 6.3 去掉空格 删除前面的空格符用lstrip()函数,后面的用rstrip(),前后都删除的,用strip()。还有一种不限位置的删除方法,那便是用replace()函数。
# 删除前面空格a = " abc"print(a.lstrip())# 删除后面的空格a = "abc "print(a.rstrip())# 删除前后的空格a = " abc "print(a.strip())# 多次空格,包括中间a = " a b c "print(a.replace("
Jenkins 是一款优秀的自动化构建服务器,利用jenkins可以帮我们解决重复繁琐的构建步骤,下面就来介绍如何搭建jenkins服务器以及如何配置项目自动化部署。
一、安装Jenkins
jenkins的安装非常简单,本质就是一个可运行的war包,java程序员都不陌生;只要将这个war包放到tomcat容器即可运行起来;
官网下载Jenkins:https://jenkins.io/zh/
将下载的war复制到tomcat的webapps目录,然后将tomcat启动即可;tomcat启动后,直接访问:http://服务器ip:8080/jenkins就会看到Jenkins界面;
第一次打开会要求输入初始密码,初始密码在tomcat的logs目录中的catalina.out日志文件中可以找到;
将初始密码填入后即可进入安装插件页面,选择推荐安装即可;
稍等片刻插件即可安装完成,但可能会出现网络问题导致插件不是全部安装成功,可以多试几次,跳过也无所谓,可后面再离线安装;
创建登陆用户;
安装并初始化完成;
由于新的jenkins版本会默认携带中文翻译插件,翻译非常渣渣,还是英文看得舒服,所以我把它卸载了。
二、jenkins配置
1. 配置maven;
选择 系统配置--全局工具配置;
填入服务器maven的settings配置文件路径;
继续往下滑,找到maven项,填入maven目录。
2. 配置jdk;
同样在全局工具配置下面;
配置java home即可,name即可。
3. 创建一个新任务;
选择第一个,名称随意,然后点击OK;
配置git仓库,用于拉取最新代码;
添加构建步骤;
选择刚刚配置的maven;
填入构建命令,就是maven的构建命令;
继续添加步骤,选择执行shell;
编写shell脚本,将maven打包出来的部署产物(jar包)启动起来;
最后点SAVE保存,至此全部配置以完成。
三、shell脚本编写思路
这里有必要解释一下shell脚本该如何编写,先把脚本贴出来,脚本很简单,理解其思路即可;
#!/bin/bash
\cp -rf /root/.jenkins/workspace/auto-comment/target/auto-comment-0.0.1-SNAPSHOT.jar /data/javaproject/auto-comment/
ps -ef | grep auto-comment-0.0.1-SNAPSHOT.jar | grep -v grep | cut -c 9-15 | xargs kill -9
cd /data/javaproject/auto-comment/
cat /dev/null > auto-comment.log
nohup java -jar auto-comment-0.0.1-SNAPSHOT.jar > auto-comment.
一、正则表达式简介
正则表达式:又称正规表示式、正规表示法、正规表达式、规则表示式、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或者是RE),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列某个句法规则的字符串。在很多文本编辑器里,正则表达式通常来检索、替换那些匹配某个模式的文本。
按某种规则匹配的表达式。
二、正则介绍
正则表达式是一个工具,用于匹配字符串,或用来提取字符串。
1、判断一个字符串是否匹配给定的格式(判断用户账号是否满足格式)
2、从字符串中,按指定格式提取信息(抓取手机号)
importre
str1= 'fijiooe18814726275iufdrrrrdf18814726275fsdssa'
#定义一个查找的规则#已知需要查找的手机号
p = '18814726275'
#search(): 从前往后查找数据,默认返回找到的第一个数据,不会再继续往后面找
res =re.search(p,str1).group()print(res)
三、元字符
表示单字符
字符
功能
.
匹配任意一个字符(除了\n)
[]
匹配[]中列举的字符
\d
匹配数字,即0-9
\D
匹配非数字,即不是数字
\s
匹配空白,即空格,tab键
\S
匹配非空白
\w
匹配单词字符,即a-z、A-Z、0-9、_
\W
匹配非单词字符
表示数量
匹配多个字符的相关格式。
字符
功能
*
匹配前一个字符出现0次或者无限次,即可有可无
+
匹配前一个字符出现1次或者无限次,即至少有1次
?
匹配前一个字符出现1次或者0次,即要么有1次,要么没有
{m}
匹配前一个字符出现m次
{m,}
匹配前一个字符至少出现m次
{m,n}
匹配前一个字符至少出现m~n次
表示边界
字符
功能
^
匹配字符串开头
$
匹配字符串结尾
\b
匹配一个单词的边界
\B
匹配非单词边界
匹配分组
字符
功能
目录
第1章 初识Python与Jupyter1
1.1 Python概要2
1.1.1 为什么要学习Python2
1.1.2 Python中常用的库2
1.2 Python的版本之争4
1.3 安装Anaconda5
1.3.1 Linux环境下的Anaconda安装5
1.3.2 conda命令的使用6
1.3.3 Windows环境下的Anaconda安装7
1.4 运行Python11
1.4.1 验证Python11
1.4.2 Python版本的Hello World12
1.4.3 Python的脚本文件13
1.4.4 代码缩进15
1.4.5 代码注释17
1.5 Python中的内置函数17
1.6 文学化编程—Jupyter20
1.6.1 Jupyter的由来20
1.6.2 Jupyter的安装21
1.6.3 Jupyter的使用23
1.6.4 Markdown编辑器26
1.7 Jupyter中的魔法函数31
1.7.1 %lsmagic函数31
1.7.2 %matplotlib inline函数32
1.7.3 %timeit函数32
1.7.4 %%writefile函数33
1.7.5 其他常用的魔法函数34
1.7.6 在Jupyter中执行shell命令35
1.8 本章小结35
1.9 思考与提高36
第2章 数据类型与程序控制结构40
2.1 为什么需要不同的数据类型41
2.2 Python中的基本数据类型42
第1章 初识Python与Jupyter1
1.1 Python概要2
1.1.1 为什么要学习Python2
1.1.2 Python中常用的库2
1.2 Python的版本之争4
1.3 安装Anaconda5
1.3.1 Linux环境下的Anaconda安装5
1.3.2 conda命令的使用6
1.3.3 Windows环境下的Anaconda安装7
1.4 运行Python11
1.4.1 验证Python11
1.4.2 Python版本的Hello World12
1.4.3 Python的脚本文件13
1.4.4 代码缩进15
1.4.5 代码注释17
第1章 初识Python与Jupyter1
1.1 Python概要2
1.1.1 为什么要学习Python2
1.1.2 Python中常用的库2
1.2 Python的版本之争4
1.3 安装Anaconda5
1.3.1 Linux环境下的Anaconda安装5
1.3.2 conda命令的使用6
1.3.3 Windows环境下的Anaconda安装7
1.4 运行Python11
1.4.1 验证Python11
1.4.2 Python版本的Hello World12
1.4.3 Python的脚本文件13
1.4.4 代码缩进15
1.4.5 代码注释17
1.5 Python中的内置函数17
1.6 文学化编程—Jupyter20
1.6.1 Jupyter的由来20
1.6.2 Jupyter的安装21
为什么需要自动化测试 自动化测试有很多优点,但这里有3个主要的点
可重用性:不需要总是编写新的脚本,除非必要,即使是新的操作系统版本也不需要编写脚本。可靠性:人容易出错,机器不太可能。当运行不能跳过的重复步骤/测试时,速度会更快。全天运行:您可以在任何时间或远程启动测试。夜间运行正在测试你的软件,即使是在你睡着的时候。 成熟的、功能齐全的Python测试工具——pytest 目前有多种可用的测试框架和工具。这些框架的风格也各不相同,比如数据驱动、关键字驱动、混合、BDD等等。您可以选择最适合您的要求。
Python和pytest在这场竞争中占据了巨大的份额。Python及其相关工具之所以被大量使用,可能是因为与其他语言相比,没有或很少编程经验的人更能负担得起它们。
pytest框架使得编写小型测试变得很容易,但是可以扩展到支持应用程序和库的复杂功能测试。
Pytest的一些主要特性:
自动发现测试模块和功能有效的CLI来更好地控制您想要运行或跳过的内容大型第三方插件生态系统固定装置-不同的类型,不同的范围与传统的单元测试框架一起工作
自动和可配置的测试发现
在默认情况下,pytest期望在名称以test_开头或以_test.py结尾的python模块中找到测试。在默认情况下,它期望测试函数名以test_ 开头。但是,可以通过在pytest的一个配置文件中添加您自己的配置来修改这个测试发现协议。
# content of pytest.ini # Example 1: have pytest look for "check" instead of "test" # can also be defined in tox.ini or setup.cfg file, although the section # name in setup.cfg files should be "tool:pytest" [pytest] python_files = check_*.py python_classes = Check python_functions = *_check 让我们看一下非常基本的测试函数。
class CheckClass(object): def one_check(self): x = "this" assert 'h' in x def two_check(self): x = "
我是谁? 我是一名从事了多年软件测试的老测试员,整理了一份最适合2020年学习的软件测试学习干货,可以送给每一位对软件测试感兴趣的小伙伴,想要获取的可以关注我的公众号:【伤心的辣条】,即可免费获取。 随着企业对测试工程师的能力要求日渐增长,对我们每一位测试工程师而言既是压力也是提升的动力,不提升就意味着没有出路,没有发展!我们职业发展的命运是靠自己的能力来把握的,而不是一味的惧怕高要求,惧怕难技术。因为只有高和难才能成就"高薪",否则只有等待"岁月催人老"了,测试能力的提升是最最关键的头等大事!
一、如何提升测试技术? 各种各样的测试技术浩如烟海,何时才能有大的突破?掌握到何种程度才能成为企业所需要的高端测试人才?如何提升?向哪个方面提升?提升的方法是什么?是否靠谱?大家只要做以下的判断就可以有明确的答案。
1、 一定要有可实践的、科学设计的测试项目和测试任务。这些测试任务不是测试知识点也更不是简单的测试工具的操作,而是系统、完整、技术覆盖全、有深度、有广度的各项自动化测试任务。
2、 以自动化测试工程师实际工作任务为驱动,而不是以测试知识点为驱动。这样在实际工作的过程中,自然能够灵活运用相关的测试技术,自然能够实现入职即可担当的目标!
3、 要有各种不同类型的自动化测试技术点,有各种不同难度的技术测试问题的分析、解决和成果。遇到的问题越多,分析的越透彻,解决的越彻底,测试能力自然越强悍!
4、 证明自己技术实力的是各种自动化测试成果物(自动化测试脚本、自动化测试框架、各种自动化技术问题的分析解决等等)
二、Python自动化测试学习路径 1、Python基础——深入学习自动化测试开发的基础
这部分主要包含python基础的语法,数据类型,数据结构,面向对象的python程序设计;
这部分对于学习能力好的人士来说,问题不大,因为都是单一的技术点,跟着一些网上现成的资源,加上自己的每日代码演练,学会应该问题不大;
当然如果要深入理解核心技术点的原理,机制等,需要查阅python官方文档及技术站点,甚至查看python源码,这就需要深入学习的能力了;
但很多初学者看到算法就头疼,其实对于测试开发岗位而言,一般的自动化测试工具对性能要求不高,跟着做几个大项目历练历练,熟练掌握编程技巧,实现业务逻辑才是重点。
2、熟悉Python常见内库
Python的优点之一就是它有非常丰富的自有库和第三方库,这也是Python开发速度快的原因之一。所以要实现业务逻辑,就需要掌握内嵌模块或者第三方模块。
3、掌握自动化测试框架和常见库
举例如下:
接口测试——Requests、Postman
性能测试——Locust
APP自动化测试——Appium、UIAutomator
Web自动化测试——Selenium
数据库的连接和操作——pymysql库
4、掌握自动化测试工具的设计思路
学习UnitTest,pytest等的设计模式,学习Jenkins,实现持续集成,快速测试,迭代。
5、实践是检验真理的唯一标准
找一个懂Python自动化测试的老师或朋友,从他们的规划和实践中找到自己的学习路线,多多请教他们,必定会事半功倍。
有"案"可测是历练我们测试技能的训练场,有了实实在在全面测试技能的提升,"测"马扬鞭当下出发!让我们一起来进行一次自动化测试案例实战吧!
请关注+私信回复:“测试”就可以获得Python自动化测试实战课程和免费软件测试学习资料! 实战过程需要的测试技术:
结合爬虫技术+web自动化测试技术+数据库技术+性能测试技术,使用爬虫抓取技术+selenium自动化测试技术+数据库存储过程技术+性能并发压测技术,通过实际测试工作任务的演练,快速通达自动化测试的彼岸!
实战过程需要解决的问题:
要进行大数量的并发压测,大批量的测试数据如何准备?
使用爬虫技术?
数据库存储过程技术?
Web自动化技术?
不同技术的应用场景及利弊分析。
如何高效、快速编写性能测试脚本,并开展性能测试执行?
如何进行性能故障定位以及性能调优?
测试工作能力如何转化到简历或面试中,成为面试官的"秒选"对象?
如果你
①从事功能测试,想进阶自动化测试
②在测试界混了1、2年,依然不会敲代码
③面试大厂却屡屡碰壁
我邀你进群吧!来吧~~测试员,313782132(Q群里有技术大牛一起交流分享,学习资源的价值取决于你的行动,莫做“收藏家”)获取更多大厂技术、面试资料
如果对python自动化测试、web自动化、接口自动化、移动端自动化、面试经验交流等等感兴趣的测试人,可以关注微信公众号:【伤心的辣条】,获取软件测试工程师大厂面试资料!
最后: 凡事要趁早,特别是技术行业,一定要提升技术功底,丰富自动化项目实战经验,这对于你未来几年职业规划,以及测试技术掌握的深度非常有帮助。
[堆入门 off-by-null] asis2016_b00ks 刚开始学pwn就听说,堆的题目很魔幻,需要大量的基础知识。在漫长地啃堆基础原理以后,这是我第一次自己研究学习并且完全明白原理的堆题。特地在此做笔记记录。
0x00 逆向分析 一进来就很容易发现,这也是堆题中最为常见的菜单题目。
简单分析一下,打开程序,最先产生交互的函数是sub_B6D。
漏洞点:sub_B6D 调用了sub_9F5函数,是作者自己写的read函数,再进去看看。
注意这里的判定:先++buf,然后判断是否达到了最大长度(32字符),如果达到了,就跳出循环,然后把当前buf的字符变为\x00。
乍一看是没什么问题,但是仔细一想,它这里的i是从0开始,当i == a2的时候其实已经读了33个字符了,也就是说如果我们刚好输入32个字符以后,它会再读一个字符,并且会把这个字符变为\x00。
比如我输入了’A’ * 32,实际上数据流中我输入的是’AAAAAAAA…AAA\n’,当我们输入的第32个A被读取之后先检测是否是’\n’,通过,++buf,然后比对i是否等于a2,但是由于i从0开始,此时i为31,所以也通过,继续循环。
然后此时读取的字符是\n,检测到*buf == ‘\n’ 所以执行break,再把’\n’覆盖为\x00。导致最终读入的字符为32个’A’+一个’\x00’。
先简单写个脚本测试一下
def create(name_size, name, desc_size, desc): global p p.recvuntil('> ') p.sendline('1') p.recvuntil(': ') p.sendline(str(name_size)) p.recvuntil(': ') p.sendline(name) p.recvuntil(': ') p.sendline(str(desc_size)) p.recvuntil(': ') p.sendline(desc) def change_author(author): global p p.recvuntil('> ') p.sendline('5') p.recvuntil(': ') p.sendline(author) def debug(): gdb.attach(p) pause() init() debug() create(0x20,'aaaaaaaa',0x20,'bbbbbbbb') debug() change_author('A'*32) debug() p.interactive() init()先将作者名设置为32个A,然后create新建一个book(因为id是1,所以咱们叫他book1),然后再change_author修改作者名,看看内存里会有什么样的变化。
1.init()执行过后
可以看到在内存里写入了32个41
2.create()执行过后
1、解线性方程组的方法大致可以分为两类:直接方法和迭代法。直接方法是指假设计算过程中不产生舍入误差,经过有限次运算可求得方程组的精确解的方法;迭代法是从解的某个近似值出发,通过构造一个无穷序列去逼近精确解的方法。
2、消去法:
Gauss(高斯)消去法——是最基本的和最简单的直接方法,它由消元过程和回代过程构成,基本思想是:将方程组逐列逐行消去变量,转化为等价的上三角形方程组(消元过程);然后按照方程组的相反顺序求解上三角形方程组,得到原方程组的解(回代过程)。
优缺点:简单易行,但是要求主元均不为0,适用范围小,数值稳定性差。列主元素消去法——基本思想是在每次消元前,在要消去未知数的系数中找到绝对值大的系数作为主元,通过方程对换将其换到主对角线上,然后进行消元。
优点:计算简单,工作量大为减少,数值稳定性良好,是求解中小型稠密线性方程组的最好方法之一。全主元素消去法——基本思想是在全体待选系数a(ij)(k)中选取主元,并通过行与列的互换把它换到a(kk)(k)的位置,进行消元。
优缺点:这种方法的精度优于列主元素法,它对控制舍入误差十分有效,但是需要同时作行列变换,因而程序比较复杂,计算时间较长。 3、直接三角分解法:消元过程实际上是把系数矩阵A分解成单位下三角形矩阵与上三角形矩阵乘积的过程,其中L为单位下三角形矩阵,U为上三角形矩阵。这种分解过程称为杜利特尔(Doolittle分解),也称为LU分解。当系数矩阵进行三角分解后,求解方程组Ax = b的问题就等价于求解两个三角形方程组Ly=b和Ux=y。
矩阵的直接三角分解——设A为n阶方阵,若A的顺序主子式A(i)均不为0,则矩阵A存在唯一的LU分解;直接三角分解法——如果线性方程组Ax = b的系数矩阵已进行三角分解A=LU,则解方程组Ax=b等价于求解两个三角形方程组Ly=b和Ux=y;列主元素的三角分解法——设矩阵A非奇异,则存在置换矩阵P,使得PA有唯一的LU分解(即PA=LU),且|l(ij)|≤1; 4、排列阵:单位矩阵经过若干次行变换所得到的矩阵。
5、克劳特(Crout)分解:将矩阵A分解成一个下三角形矩阵L与一个单位上三角形矩阵U的乘积。
6、特殊矩阵的三角分解法:在工程实际计算中,如三次样条插值或用差分法求解常微分方程边值问题,导出的线性方程组的系数矩阵A常常是稀疏的三对角形矩阵或A是对称正定阵,使得A的三角分解也具有更简洁的形式。
解三对角方程组的追赶法——三对角矩阵为非零元素集中分布在主对角线及其相邻的两条次对角线上的矩阵。
设图中的系数矩阵A满足下列条件
则A可唯一分解为
平方根法(Cholesky分解法)——设A是正定矩阵,则存在唯一的非奇异下三角形矩阵L,使得A=LLT ,且L的对角元素皆为正数。当矩阵A完成Cholesky分解后,求解方程组Ax=b就转化为依次求解方程组Ly = b,LTx = y。
优缺点:无需选择主元,计算过程也是稳定的,数量级约是Gauss消去法的一半,在求L时需做n次开方运算,故而增加了计算量。
改进平方根法(LDLT法)——对称正定矩阵A又可以作如下分解,A=LDLT ,其中L为单位下三角形矩阵,D为对角阵,记为
平方根法与改进平方根法不仅计算量仅是Gauss消去法的一半,其数值稳定性也十分良好,是求解中小型稠密对称正定线性方程组的好方法。
4.分块三角分解法——在求解微分方程数值解时,如果用差分法或有限元法离散微分方程,导出线性方程组往往是稀疏的,而且具有分块结构,这些稀疏性和分块性对于提高求解方程组的效率很有帮助。
7、向量范数:是衡量向量大小的度量概念,可以用来刻画Rn 中向量序列的收敛性。
向量x的范数具体形式有很多,常用的有以下三种:
(1)2 - 范数(向量的模)
(2)1 - 范数
(3)∞ - 范数
8、范数等价定理:Rn 中任意两种范数都是等价的。
9、矩阵范数:类似于向量范数的定义,可以定义n x n阶矩阵的范数。
常用的矩阵范数有四种,前三种是由向量的1-范数,2-范数,∞-范数诱导出的矩阵范数。设A = (a(ij))为n阶方阵
(1)1 - 范数(列范数)
(2)∞ - 范数(行范数)
(3)2 - 范数(谱范数)
其中λ是矩阵ATA的最大特征值
(4)F - 范数
10、设A*是A的近似矩阵,||A - A* ||,||A - A* || / ||A||分别称为A* 关于范数|| • ||的绝对误差和相对误差,并且由向量范数的等价性可得矩阵范数的等价性。
ingress-nginx配置(注解) 注解 您可以将这些Kubernetes批注添加到特定的Ingress对象,以自定义其行为。
小费
注释键和值只能是字符串。其他类型,如布尔或数值必须被引用,即"true","false","100"。
注意
可以使用--annotations-prefix命令行参数更改注释前缀 ,但默认值为nginx.ingress.kubernetes.io,如下表所述。
Nametypenginx.ingress.kubernetes.io/app-rootstringnginx.ingress.kubernetes.io/affinitycookienginx.ingress.kubernetes.io/affinity-mode"balanced" or "persistent"nginx.ingress.kubernetes.io/auth-realmstringnginx.ingress.kubernetes.io/auth-secretstringnginx.ingress.kubernetes.io/auth-secret-typestringnginx.ingress.kubernetes.io/auth-typebasic or digestnginx.ingress.kubernetes.io/auth-tls-secretstringnginx.ingress.kubernetes.io/auth-tls-verify-depthnumbernginx.ingress.kubernetes.io/auth-tls-verify-clientstringnginx.ingress.kubernetes.io/auth-tls-error-pagestringnginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream"true" or "false"nginx.ingress.kubernetes.io/auth-urlstringnginx.ingress.kubernetes.io/auth-cache-keystringnginx.ingress.kubernetes.io/auth-cache-durationstringnginx.ingress.kubernetes.io/auth-proxy-set-headersstringnginx.ingress.kubernetes.io/auth-snippetstringnginx.ingress.kubernetes.io/enable-global-auth"true" or "false"nginx.ingress.kubernetes.io/backend-protocolstringnginx.ingress.kubernetes.io/canary"true" or "false"nginx.ingress.kubernetes.io/canary-by-headerstringnginx.ingress.kubernetes.io/canary-by-header-valuestringnginx.ingress.kubernetes.io/canary-by-header-patternstringnginx.ingress.kubernetes.io/canary-by-cookiestringnginx.ingress.kubernetes.io/canary-weightnumbernginx.ingress.kubernetes.io/client-body-buffer-sizestringnginx.ingress.kubernetes.io/configuration-snippetstringnginx.ingress.kubernetes.io/custom-http-errors[]intnginx.ingress.kubernetes.io/default-backendstringnginx.ingress.kubernetes.io/enable-cors"true" or "false"nginx.ingress.kubernetes.io/cors-allow-originstringnginx.ingress.kubernetes.io/cors-allow-methodsstringnginx.ingress.kubernetes.io/cors-allow-headersstringnginx.ingress.kubernetes.io/cors-allow-credentials"true" or "false"nginx.ingress.kubernetes.io/cors-max-agenumbernginx.ingress.kubernetes.io/force-ssl-redirect"true" or "false"nginx.ingress.kubernetes.io/from-to-www-redirect"true" or "false"nginx.ingress.kubernetes.io/http2-push-preload"true" or "false"nginx.ingress.kubernetes.io/limit-connectionsnumbernginx.ingress.kubernetes.io/limit-rpsnumbernginx.ingress.kubernetes.io/permanent-redirectstringnginx.ingress.kubernetes.io/permanent-redirect-codenumbernginx.ingress.kubernetes.io/temporal-redirectstringnginx.ingress.kubernetes.io/proxy-body-sizestringnginx.ingress.kubernetes.io/proxy-cookie-domainstringnginx.ingress.kubernetes.io/proxy-cookie-pathstringnginx.ingress.kubernetes.io/proxy-connect-timeoutnumbernginx.ingress.kubernetes.io/proxy-send-timeoutnumbernginx.ingress.kubernetes.io/proxy-read-timeoutnumbernginx.ingress.kubernetes.io/proxy-next-upstreamstringnginx.ingress.kubernetes.io/proxy-next-upstream-timeoutnumbernginx.ingress.kubernetes.io/proxy-next-upstream-triesnumbernginx.ingress.kubernetes.io/proxy-request-bufferingstringnginx.ingress.kubernetes.io/proxy-redirect-fromstringnginx.ingress.kubernetes.io/proxy-redirect-tostringnginx.ingress.kubernetes.io/proxy-http-version"1.0" or "1.1"nginx.ingress.kubernetes.io/proxy-ssl-secretstringnginx.ingress.kubernetes.io/proxy-ssl-ciphersstringnginx.ingress.kubernetes.io/proxy-ssl-namestringnginx.ingress.kubernetes.io/proxy-ssl-protocolsstringnginx.ingress.kubernetes.io/proxy-ssl-verifystringnginx.ingress.kubernetes.io/proxy-ssl-verify-depthnumbernginx.ingress.kubernetes.io/enable-rewrite-log"true" or "false"nginx.ingress.kubernetes.io/rewrite-targetURInginx.ingress.kubernetes.io/satisfystringnginx.ingress.kubernetes.io/server-aliasstringnginx.ingress.kubernetes.io/server-snippetstringnginx.ingress.kubernetes.io/service-upstream"true" or "false"nginx.ingress.kubernetes.io/session-cookie-namestringnginx.ingress.kubernetes.io/session-cookie-pathstringnginx.ingress.kubernetes.io/session-cookie-change-on-failure"true" or "false"nginx.ingress.kubernetes.io/session-cookie-samesitestringnginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none"true" or "false"nginx.ingress.kubernetes.io/ssl-redirect"true" or "false"nginx.ingress.kubernetes.io/ssl-passthrough"true" or "false"nginx.ingress.kubernetes.io/upstream-hash-bystringnginx.ingress.kubernetes.io/x-forwarded-prefixstringnginx.ingress.kubernetes.io/load-balancestringnginx.ingress.kubernetes.io/upstream-vhoststringnginx.ingress.kubernetes.io/whitelist-source-rangeCIDRnginx.ingress.kubernetes.io/proxy-bufferingstringnginx.ingress.kubernetes.io/proxy-buffers-numbernumbernginx.ingress.kubernetes.io/proxy-buffer-sizestringnginx.ingress.kubernetes.io/proxy-max-temp-file-sizestringnginx.ingress.kubernetes.io/ssl-ciphersstringnginx.ingress.kubernetes.io/connection-proxy-headerstringnginx.ingress.kubernetes.io/enable-access-log"true" or "false"nginx.ingress.kubernetes.io/enable-opentracing"true" or "false"nginx.ingress.kubernetes.io/enable-influxdb"true" or "false"nginx.ingress.kubernetes.io/influxdb-measurementstringnginx.ingress.kubernetes.io/influxdb-portstringnginx.ingress.kubernetes.io/influxdb-hoststringnginx.ingress.kubernetes.io/influxdb-server-namestringnginx.ingress.kubernetes.io/use-regexboolnginx.ingress.kubernetes.io/enable-modsecurityboolnginx.ingress.kubernetes.io/enable-owasp-core-rulesboolnginx.ingress.kubernetes.io/modsecurity-transaction-idstringnginx.ingress.kubernetes.io/modsecurity-snippetstringnginx.ingress.kubernetes.io/mirror-request-bodystringnginx.ingress.kubernetes.io/mirror-targetstring 金丝雀 在某些情况下,您可能希望通过向少量与生产服务不同的服务发送少量请求来“取消”一组新的更改。Canary注释使Ingress规范可以充当路由请求的替代服务,具体取决于所应用的规则。nginx.ingress.kubernetes.io/canary: "true"设置后,可以启用以下用于配置金丝雀的注释:
nginx.ingress.kubernetes.io/canary-by-header:用于通知Ingress将请求路由到Canary Ingress中指定的服务的标头。当请求标头设置always为时,它将被路由到Canary。当标头设置never为时,它将永远不会路由到金丝雀。对于任何其他值,标头将被忽略,并且按优先级将请求与其他金丝雀规则进行比较。
nginx.ingress.kubernetes.io/canary-by-header-value:匹配的报头值,用于通知Ingress将请求路由到Canary Ingress中指定的服务。当请求标头设置为此值时,它将被路由到Canary。对于任何其他标头值,标头将被忽略,并按优先级将请求与其他金丝雀规则进行比较。此注释必须与一起使用。注释是的扩展,nginx.ingress.kubernetes.io/canary-by-header允许自定义标头值,而不使用硬编码值。如果nginx.ingress.kubernetes.io/canary-by-header未定义注释,则没有任何作用。
nginx.ingress.kubernetes.io/canary-by-header-pattern:这与canary-by-header-valuePCRE Regex匹配相同。请注意,canary-by-header-value设置时,此注释将被忽略。当给定的正则表达式在请求处理期间导致错误时,该请求将被视为不匹配。
nginx.ingress.kubernetes.io/canary-by-cookie:用于通知Ingress将请求路由到Canary Ingress中指定的服务的cookie。当cookie值设置always为时,它将被路由到canary。当cookie设置never为时,它将永远不会路由到Canary。对于任何其他值,将忽略cookie,并按优先级将请求与其他canary规则进行比较。
nginx.ingress.kubernetes.io/canary-weight:随机请求的整数百分比(0-100),应将其路由到canary Ingress中指定的服务。权重0表示此Canary规则不会在Canary入口中将任何请求发送到服务。权重为100表示所有请求都将发送到Ingress中指定的替代服务。
金丝雀规则按优先级进行评估。优先级如下: canary-by-header -> canary-by-cookie -> canary-weight
请注意,当您将某个入口标记为canary时,除nginx.ingress.kubernetes.io/load-balance和之外,所有其他非canary注释将被忽略(从相应的主要入口继承)nginx.ingress.kubernetes.io/upstream-hash-by。
达梦数据库创建定时作业 1、新建代理环境2、新建定时全备、增备作业2.1 作业名及作业描述2.2 作业步骤2.2.1 常规2.2.2 作业步骤2.2.3 作业调度2.2.4 DDL2.2.5 增备与全备全备的区别 3、定时作业执行SQL脚本3.3.1 常规3.3.2 作业步骤3.3.2.1 调用系统存储过程 使用DM管理工具代理作业进行定时备份或执行脚本,此次,我分享一下我创建定时作业的步骤。 1、新建代理环境 2、新建定时全备、增备作业 右键作业,点击“新建作业”
2.1 作业名及作业描述 2.2 作业步骤 2.2.1 常规 选择“添加”按钮
2.2.2 作业步骤 2.2.3 作业调度 新建作业调度不做截图
2.2.4 DDL 也可使用disql等后台方式创建以上步骤,上述步骤的SQL如下:
call SP_CREATE_JOB(‘全备’,1,0,’’,0,0,’’,0,‘每周六晚23点全备’);
call SP_JOB_CONFIG_START(‘全备’);
call SP_ADD_JOB_STEP(‘全备’, ‘完全备份’, 6, ‘01000000E:\dmdbms\dmbak’, 1, 2, 0, 0, NULL, 0);
call SP_ADD_JOB_SCHEDULE(‘全备’, ‘每周六全备’, 1, 2, 1, 64, 0, ‘23:00:00’, NULL, ‘2020-12-01 15:28:06’, NULL, ‘’);
call SP_JOB_CONFIG_COMMIT(‘全备’);
2.2.5 增备与全备全备的区别 1、增备时,要输入基备份集目录,可新增后添加默认路径并更改基备份路径。
2、增备建议每日执行(全备日(例如周六)除外)
3、增备DDL
call SP_CREATE_JOB(‘增备’,1,0,’’,0,0,’’,0,‘每周日、1、2、3、4、5执行增备’);
达梦分析归档日志方法 查看数据库归档信息,使用DM管理工具查询或手动查看归档目录添加需要分析的归档日志确认归档日志是否被加载启动日志分析查看v$logmnr_contents视图找出对应的操作停止分析v$logmnr_contents视图分析所有的操作日志。 在很多场合下,我们需要分析数据库操作日志来确认是否对数据库是否存在误操作,类似删表和删除数据等操作。这个时候就可以使用logmnr工具来分析归档日志。 1、首先确保数据库处于归档模式下,且保留的归档文件日志包含误操作日志。 2、确保RLOG_APPEND_LOGIC为1或者2,如果为0,归档文件记录的操作会很少。 查看数据库归档信息,使用DM管理工具查询或手动查看归档目录 select first_time,name from v$archived_log;
或者进入归档目录查看
服务器查询归档需要进入归档路径查看。
添加需要分析的归档日志 Call dbms_logmnr.add_logfile(’/dbbak/db7bak/arch/ARCHIVE_LOCAL1_20161013025146670_0.log’);
Call dbms_logmnr.add_logfile(’ E:\dmdbms\dmarch\ARCHIVE_LOCAL1_0x3D2E02C4[0]_2020-12-01_17-41-45.log’);
每次call只能添加一条归档,可以执行多条call;
确认归档日志是否被加载 Select * from v$logmnr_logs;
启动日志分析 DBMS_LOGMNR.START_LOGMNR(OPTIONS=>2128,STARTTIME=>TO_DATE(‘2020-11-20 14:31:49.702000’,‘YYYY-MM-DD HH24:MI:SS’) ,ENDTIME=>TO_DATE(‘2020-11-23 17:54:13.507000’,‘YYYY-MM-DD HH24:MI:SS’));
其中STARTTIME=查询结果中的LOW_TIME;ENDTIME=HIGH_TIME
查看v$logmnr_contents视图找出对应的操作 select start_timestamp,sql_redo from v$logmnr_contents where table_name='TABLES' and operation='DELETE' and sql_redo like '%000300008617%'; 停止分析v$logmnr_contents视图分析所有的操作日志。 DBMS_LOGMNR.END_LOGMNR
一、保存、读取说明 我们创建好模型之后需要保存模型,以方便后续对模型的读取与调用,保存模型我们可能有下面三种需求:1、只保存模型权重参数;2、同时保存模型图结构与权重参数;3、在训练过程的检查点保存模型数据。下面分别对这三种需求进行实现。
二、仅保存模型参数 仅保存模型参数可以用一下的API:
Model.save_weights(file_path) # 将文件保存到save_path
Model.load_weights(file_path) # 将文件读取到save_path
注意:由于save_weights只是保存权重w、b的参数值,所以在加载时最好保证我们的模型结构和原来保存的模型结构是相同的,否则可能会报错。.
模型在保存之后会有多个文件:
index类型文件,在分布式计算中,索引文件会指示哪些权重存储在哪个分片。checkpoint类型文件,检查文件点包含: 一个或多个包含模型权重的分片如果您只在一台机器上训练模型,那么您将有一个带有后缀的分片:.data-00000-of-00001 import tensorflow as tf import os # 读取数据集 (train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.fashion_mnist.load_data() # 数据集归一化 train_images = train_images / 255 train_labels = train_labels / 255 # 进行数据的归一化,加快计算的进程 # 创建模型结构 net_input=tf.keras.Input(shape=(28,28)) fl=tf.keras.layers.Flatten()(net_input)#调用input l1=tf.keras.layers.Dense(32,activation="relu")(fl) l2=tf.keras.layers.Dropout(0.5)(l1) net_output=tf.keras.layers.Dense(10,activation="softmax")(l2) # 创建模型类 model = tf.keras.Model(inputs=net_input, outputs=net_output) # 查看模型的结构 model.summary() # 模型编译 model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001), loss="sparse_categorical_crossentropy", metrics=['acc']) # 模型训练 model.fit(train_images, train_labels, batch_size=50, epochs=5, validation_split=0.
在keras中,保存.h5模型可能出现两种保存方法:
即(1)保存模型权重和网络结构,以及(2)只保存模型权重。
.h5转.pb的两种方式:
方法一:
Keras的.h5模型转成tensorflow的.pb格式模型,方便后期的前端部署。直接上代码
from keras.models import Model
from keras.layers import Dense, Dropout
from keras.applications.mobilenet import MobileNet
from keras.applications.mobilenet import preprocess_input
from keras.preprocessing.image import load_img, img_to_array
import tensorflow as tf
from keras import backend as K
import os
base_model = MobileNet((None, None, 3), alpha=1, include_top=False, pooling='avg', weights=None)
x = Dropout(0.75)(base_model.output)
x = Dense(10, activation='softmax')(x)
model = Model(base_model.input, x)
model.load_weights('mobilenet_weights.h5')
def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
from tensorflow.python.framework.graph_util import convert_variables_to_constants
linux如何查进程、杀进程,重启进程 1.查进程
ps命令查找与进程相关的PID号:
ps a 显示现行终端机下的所有程序,包括其他用户的程序。
ps -A 显示所有程序。
ps c 列出程序时,显示每个程序真正的指令名称,而不包含路径,参数或常驻服务的标示。
ps -e 此参数的效果和指定"A"参数相同。
ps e 列出程序时,显示每个程序所使用的环境变量。
ps f 用ASCII字符显示树状结构,表达程序间的相互关系。
ps -H 显示树状结构,表示程序间的相互关系。
ps -N 显示所有的程序,除了执行ps指令终端机下的程序之外。
ps s 采用程序信号的格式显示程序状况。
ps S 列出程序时,包括已中断的子程序资料。
ps -t<终端机编号> 指定终端机编号,并列出属于该终端机的程序的状况。
ps u 以用户为主的格式来显示程序状况。
ps x 显示所有程序,不以终端机来区分。
最常用的方法是ps aux,然后再通过管道使用grep命令过滤查找特定的进程,然后再对特定的进程进行操作。 ps aux | grep program_filter_word,ps -ef |grep tomcat ps -ef|grep java|grep -v grep 显示出所有的java进程,去处掉当前的grep进程。
2.杀进程
显示CPU使用情况以及部分进程:top
显示连接端口使用进程:netstat -noap/-an |grep NAME
使用kill命令结束进程:kill xxx
常用:kill -9 324
jenkins 1. jenkins介绍2. jenkins安装3. jenkins相关文件解析4. 通过jenkins发布php代码5. jenkins邮件配置6. 插件email-ext7. 破解管理员密码8. 部署java项目-创建私有仓库9. 部署java项目-下载zrlog源码10. 安装tomcat 1. jenkins介绍 持续集成是什么 互联网软件的开发和发布,已经形成了一套标准流程,最重要的组成部分就是持续集成(Continuous integration,简称CI)。 持续集成指的是,频繁地(一天多次)将代码集成到主干 它的好处主要有两个
1. 快速发现错误。每完成一点更新,就集成到主干,可以快速发现错误,定位错误也比较容易。 2. 防止分支大幅偏离主干。如果不是经常集成,主干又在不断更新,会导致以后集成的难度变大,甚至难以集成。 持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。 Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。" 与持续集成相关的,还有两个概念,分别是持续交付和持续部署。 持续交付 持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。如果评审通过,代码就进入生产阶段。 持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的。 持续部署 持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。 持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段。 持续部署的前提是能自动化完成测试、构建、部署等步骤。它与持续交付的区别,可以参考下图。 参考链接: http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html 2. jenkins安装 jenkins的官方文档地址 https://www.jenkins.io/zh/
安装jenkins的最低配置: 不少于256M内存,不低于1G磁盘,jdk版本>=8,如果只需要java的运行环境的话,用yum安装个openjdk就可以了,安装命令如下 yum install -y java-1.8.0-openjdk #系统自带安装 官网下载安装jdk1.8 1. tar zxvf jdk-8u101-linux-x64.tar.gz #解压包 2. mv jdk1.8.0_101/ /usr/local/jdk1.8 #移动并改名 下载jenkins的yum源 wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo 安装jenkins.io.key rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key yum安装jenkins yum install -y jenkins 修改jenkins配置文件 1.
代码管理平台 git 1. 单机上使用git2. 建立远程仓库3. 克隆远程仓库4. git本地分支管理5. 使用分支的原则6. git远程分支管理7. git标签管理8. git别名 1. 单机上使用git git是分布式的仓库,我们不需要把代码上传或更新到某个特定的服务器上,所以它不需要依赖网络,我们可以在本地创建一个git仓库。
git安装命令 yum install -y git 创建git仓库 mkdir /data/gitroot/ git 初始化仓库 1. cd /data/gitroot/ 2. git init #初始化git仓库 Initialized empty Git repository in /data/gitroot/.git/ #初始化空的 Git 版本库于 /data/gitroot/.git/ 3. [root@test01 gitroot]# ls -la . total 0 drwxr-xr-x. 3 root root 18 Nov 23 14:31 . drwxr-xr-x. 5 root root 49 Nov 23 14:30 .. drwxr-xr-x. 7 root root 119 Nov 23 14:31 .
嗯, 该场景是产品经理给我一个excel表格里面有多个国家名
前端需要的数据结构是要展示成键值对的形式 形如 { text: '阿富汗', value: 1 } // value 值大于1 不重复就行 我的处理过程 选中一列 复制到 vs code 中(重复直到复制完) 对齐处理 (有些数据可能是不对齐的) 从缩略图这里也可以看得出来 光标置于前面的数据中 按住 shift + alt (不同编辑器快捷键不一样) 这样就可以选中多行 然后输入 # 号 或者其他符号 字母等 一会用来做分割用 光标移动到#号前面 删掉多余空格 保证只占用一行 然后就没有然后了 逻辑一上 万事解决 var str =`阿富汗#亚美尼亚#阿塞拜疆#巴林#孟加拉国#文莱#柬埔寨#朝鲜#东帝汶#格鲁吉亚#印度#印度尼西亚#伊朗#伊拉克#以色列#日本#约旦#哈萨克斯坦#科威特#吉尔吉斯斯坦#老挝#黎巴嫩#马来西亚#马尔代夫#蒙古#缅甸#尼泊尔#阿曼#巴基斯坦#巴勒斯坦#菲律宾#卡塔尔#韩国#沙特阿拉伯#新加坡#斯里兰卡#叙利亚#塔吉克斯坦#泰国#土耳其#土库曼斯坦#阿拉伯联合酋长国#乌兹别克斯坦#越南#也门#阿尔及利亚#安哥拉#贝宁#博茨瓦纳#布基纳法索#布隆迪#喀麦隆#佛得角#中非#乍得#科摩罗#刚果(金)#刚果(布)#科特迪瓦#吉布提#埃及#赤道几内亚#厄立特里亚#埃塞俄比亚#加蓬#冈比亚#加纳#几内亚#几内亚比绍#肯尼亚#莱索托#利比里亚#利比亚#马达加斯加#马拉维#马里#毛里塔尼亚#毛里求斯#摩洛哥#莫桑比克#纳米比亚#尼日尔#尼日利亚#卢旺达#圣多美和普林西比#塞内加尔#塞舌尔#塞拉利昂#索马里#南非#南苏丹#苏丹#坦桑尼亚#多哥#突尼斯#乌干达#赞比亚#津巴布韦#阿尔巴尼亚#安道尔#奥地利#白俄罗斯#比利时#波斯尼亚和黑塞哥维那#保加利亚#克罗地亚#塞浦路斯#捷克#丹麦#爱沙尼亚#芬兰#法国#德国#希腊#匈牙利#冰岛#爱尔兰#意大利#拉脱维亚#列支敦士登#立陶宛#卢森堡#马耳他#摩尔多瓦#摩纳哥#黑山#荷兰#北马其顿#挪威#波兰#葡萄牙#罗马尼亚#俄罗斯#圣马力诺#塞尔维亚#斯洛伐克#斯洛文尼亚#西班牙#瑞典#瑞士#乌克兰#英国#安提瓜和巴布达#阿根廷#巴哈马#巴巴多斯#玻利维亚#巴西#加拿大#智利#哥伦比亚#哥斯达黎加#古巴#多米尼克#多米尼加#厄瓜多尔#萨尔瓦多#格林纳达#圭亚那#牙买加#墨西哥#巴拿马#秘鲁#苏里南#特立尼达和多巴哥#美国#乌拉圭#委内瑞拉#澳大利亚#库克群岛#斐济#基里巴斯#密克罗尼西亚#新西兰#纽埃#巴布亚新几内亚#萨摩亚#所罗门群岛#汤加#瓦努阿图` var arr = str.split("#") var list = [] var list1 = [] var list2= [] for(var i =0; i<arr.length; i++){ var obj = { text: arr[i], value: i+1 } // 这里做了分三段输出 因为 vs code 打印数组过长时 会省略掉 if(i<70){ list.