1.请问哪位有模拟退火遗传算法的源程序?
2.python基础教程(代码编程教学入门)
3.statfs系统调用
4.runc hang 导致 Kubernetes 节点 NotReady
请问哪位有模拟退火遗传算法的源程序?
遗传算法求解f(x)=xcosx+2的最大值
其中在尺度变换部分应用到了类似模拟退火算法部分,所有变量均使用汉语拼音很好懂
//中国电子科技集团公司
//第一研究室
//呼文韬
//hu_hu@.com
//随机初始种群
//编码方式为格雷码
//选择方法为随机遍历
//采用了精英保存策略
//采用了自适应的交叉率和变异率
//采用了与模拟退火算法相结合的尺度变换
//采用了均匀交叉法
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <iostream.h>
#include <iomanip.h>
#include <time.h>
#include <windows.h>
#define IM1
#define IM2
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1
#define IA2
#define IQ1
#define IQ2
#define IR1
#define IR2
#define NTAB
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
#define zhizhenjuli 0.
#define PI 3.
#define T0 //温度要取得很高才行。
#define zhongqunshu1
#define zuobianjie -
#define youbianjie
unsigned int seed=0; //seed 为种子,要设为全局变量
void mysrand(long int i) //初始化种子
{
seed = -i;
}
long a[1];
//double hundun;
//double c=4;
//设置全局变量
struct individual
{
unsigned *chrom; //染色体;
double geti;//变量值
double shiyingdu; //目标函数的值;
double fitness; //变换后的适应度值;
};
individual *zuiyougeti;//精英保存策略
int zhongqunshu; //种群大小
individual *nowpop;//当前代
individual *newpop;//新一代
double sumfitness;//当代的总适应度fitness
double sumshiyingdu;//当代的总适应度shiyingdu
double maxfitness;//最大适应度
double avefitness;//平均适应度
double maxshiyingdu;//最大适应度
double avgshiyingdu;//平均适应度
float pc;//交叉概率
float pm;//变异概率
int lchrom;//染色体长度
int maxgen;//最大遗传代数
int gen;//遗传代数
//函数
int flipc(double ,double );//判断是否交叉
int flipm(double );//判断是否变异
int rnd(int low,int high);//产生low与high之间的任意数
void initialize();//遗传算法初始化
void preselectfitness(); //计算sumfiness,avefitness,maxfitness
void generation();
double suijibianli();//产生随机遍历指针
int fuzhi(float );//选择要复制的个体
void crossover(individual ,individual ,individual &,individual &);//交叉
void bianyi(individual &);//变异
void mubiaohanshu(individual &);//计算适应度
void chidubianhuan(individual &);//对shiyingdu进行尺度变换赋给fitness
double ran1(long *);//随机数初始
void bianma(double bianliang,unsigned *p);//编码
double yima(unsigned *p);
void guanjiancanshujisuan();//计算shiyingdu,根据shiyingdu计算sumshiyingdu,对shiyingdu进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
void jingyingbaoliu();
void glp(int n,snake模型 源码int s,int *,int (*)[1],float (*)[1]);//glp生成函数
BOOL Exist(int Val, int Num, int *Array);//判断一个数在前面是否出现过
int cmpfitness(const void *p1,const void *p2)
{
float i=((individual *)p1)->shiyingdu;//现在是按照"适应度"排序,改成"个体"的话就是按照"个体"排序
float j=((individual *)p2)->shiyingdu;
return i<j ? -1:(i==j ? 0:1);//现在是按升序牌排列,将1和-1互换后就是按降序排列
}
void main()
{
initialize();
cout<<zuiyougeti->geti<<" "<<zuiyougeti->shiyingdu<<endl;/////////////
for(gen=1;gen<maxgen;gen++)
{ generation();
}
jingyingbaoliu();
cout<<setiosflags(ios::fixed)<<setprecision(6)<<zuiyougeti->geti<<" "<<setiosflags(ios::fixed)<<setprecision(6)<<(zuiyougeti->shiyingdu)<<endl;////////////////
delete [] newpop;
delete [] nowpop;
delete [] zuiyougeti;
system("pause");
}
void initialize()
{
int q[zhongqunshu1][1],s=1;
float xx[zhongqunshu1][1];//生成的glp用x储存
int h[1]={ 1};//生成向量
zuiyougeti=new individual;//最优个体的生成
zhongqunshu=;//种群数量
nowpop=new individual[zhongqunshu1];//当代
newpop=new individual[zhongqunshu1];//新一代
maxgen=;//最大代数
gen=0;//起始代
lchrom=;//基因数量的初始化
mysrand(time(0));//随机数种子
a[0]=seed;//随机数种子
//对最优个体的初始化
zuiyougeti->geti=0;
zuiyougeti->fitness=0;
zuiyougeti->shiyingdu=0;
//
glp(zhongqunshu,s,h,q,xx);
//for(int i=0;i<zhongqunshu1;i++)//产生初始种群
//{
// for(int j=0;j<s;j++)
// {
// nowpop[i].geti=zuobianjie+(youbianjie-zuobianjie)*xx[i][j];
// }
//}
for(int i=0;i<zhongqunshu1;i++)//产生初始种群
{
nowpop[i].geti=zuobianjie+(youbianjie-(zuobianjie))*ran1(a);
}
//nowpop[0].geti=;//////////////////////////
guanjiancanshujisuan();
jingyingbaoliu(); //精英保留的实现
guanjiancanshujisuan();//计算shiyingdu,根据shiyingdu计算sumshiyingdu,对shiyingdu进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
}
void jingyingbaoliu() //精英保留的实现
{
individual *zuiyougetiguodu;
zuiyougetiguodu=new individual[zhongqunshu1];//建立一个过渡数组
for(int i=0;i<zhongqunshu;i++)//将当代个体复制到过渡数组中
zuiyougetiguodu[i]=nowpop[i];
qsort(zuiyougetiguodu,zhongqunshu1,sizeof(individual),&cmpfitness);//按fitness升序排序
// cout<<"zuiyougetiguodu适应度:"<<zuiyougetiguodu[zhongqunshu1-1].shiyingdu<<endl;///////////
// cout<<"zuiyougeti适应度:"<<zuiyougeti->shiyingdu<<endl;///////////////////
//system("pause");
if(zuiyougetiguodu[zhongqunshu-1].shiyingdu>zuiyougeti->shiyingdu)
{
*zuiyougeti=zuiyougetiguodu[zhongqunshu1-1];//如果最优个体的fitness比当代最大的fitness小则用当代的代替之
//cout<<"zuiyougetiguodu个体:"<<zuiyougetiguodu[zhongqunshu1-1].geti<<endl;/////////////
//cout<<"zuiyougeti个体:"<<zuiyougeti->geti<<endl;/////////////
}
else
nowpop[rnd(0,(zhongqunshu1-1))]=*zuiyougeti;//否则的话从当代中随机挑选一个用最优个体代替之
delete [] zuiyougetiguodu;//释放过渡数组
}
void guanjiancanshujisuan()//计算shiyingdu,根据shiyingdu计算sumshiyingdu,对shiyingdu进行尺度变换变成fitness,根据fitness计算sumfitness,avefitness,maxfitness
{
for(int i=0;i<zhongqunshu;i++)//计算shiyingdu
mubiaohanshu(nowpop[i]);
for(i=0;i<zhongqunshu;i++)//对shiyingdu进行尺度变换变成fitness
chidubianhuan(nowpop[i]);
preselectfitness();//根据fitness计算sumfitness,avefitness,maxfitness
}
void mubiaohanshu(individual &bianliang)//计算shiyingdu
{
bianliang.shiyingdu=(bianliang.geti*cos(bianliang.geti)+2.0);//目标函数
}
void chidubianhuan(individual &bianliang)//对shiyingdu进行尺度变换变成fitness
{
double T;//退火温度
T=T0*(pow(0.,(gen+1-1)));
double sum=0;
for(int j=0;j<zhongqunshu;j++)
sum+=exp(nowpop[j].shiyingdu/T);
bianliang.fitness=exp(bianliang.shiyingdu/T)/sum;//算出fitness
}
void preselectfitness()//根据fitness计算sumfitness,avefitness,maxfitness
{
int j;
sumfitness=0;
for(j=0;j<zhongqunshu;j++)
sumfitness+=nowpop[j].fitness;
individual *guodu;
guodu=new individual[zhongqunshu1];
for(j=0;j<zhongqunshu;j++)
guodu[j]=nowpop[j];
qsort(guodu,zhongqunshu1,sizeof(individual),&cmpfitness);
maxfitness=guodu[zhongqunshu1-1].fitness;
avefitness=sumfitness/zhongqunshu1;
delete [] guodu;
}
void generation()
{
individual fuqin1,fuqin2,*pipeiguodu,*pipeichi;
int *peiduishuzu;//用来存放产生的随机配对
pipeiguodu=new individual[zhongqunshu1];
pipeichi=new individual[zhongqunshu1];
peiduishuzu=new int[zhongqunshu1];
int member1,member2,j=0,fuzhijishu=0,i=0,temp=0,tt=0;
float zhizhen;
//随机遍历的实现
for(zhizhen=suijibianli();zhizhen<1;(zhizhen=zhizhen+zhizhenjuli))//设定指针1/
{
pipeichi[fuzhijishu]=nowpop[fuzhi(zhizhen)];
fuzhijishu++;
}
//交叉与变异的实现
//交叉
for(i=0;i<zhongqunshu1;i++)
{
peiduishuzu[i]=-1;
}
for (i=0; i<zhongqunshu1; i++)
{
temp =rnd(0,zhongqunshu1-1); //产生值在0-zhongqunshu1-1的随机数
while(Exist(temp, i, peiduishuzu))//判断产生的随机数是否已经产生过,如果是,则再产生一个随机数
{
temp =rnd(0,zhongqunshu1-1);
}
//如果没有的话,则把产生的随机数放在peiduishuzu中
*(peiduishuzu+i) = temp;
}
for(i=0;i<zhongqunshu1-1;i=i+2)
{
fuqin1=pipeichi[peiduishuzu[i]];
fuqin2=pipeichi[peiduishuzu[i+1]];
crossover(fuqin1,fuqin2,newpop[i],newpop[i+1]);
}
for(j=0;j<zhongqunshu1;j++)
{
//if(newpop[j].geti<-)
//cout<<"个体数值小于下界了";
nowpop[j].geti=newpop[j].geti;
}
//
guanjiancanshujisuan();
//变异的实现
for(j=0;j<zhongqunshu;j++)
{
bianyi(nowpop[j]);
}
//
guanjiancanshujisuan();
//精英保留的实现
jingyingbaoliu();
//
guanjiancanshujisuan();
delete [] peiduishuzu;
delete [] pipeichi;
delete [] pipeiguodu;
}
void crossover(individual parent1,individual parent2,individual &child1,individual &child2)//交叉
{
int j;
unsigned *panduan;
panduan=new unsigned[lchrom];
parent1.chrom=new unsigned[lchrom];
parent2.chrom=new unsigned[lchrom];
child1.chrom=new unsigned[lchrom];
child2.chrom=new unsigned[lchrom];
//cout<<"jiaocha"<<endl;///////////////////////
bianma(parent1.geti,parent1.chrom);
bianma(parent2.geti,parent2.chrom);
if(flipc(parent1.fitness,parent2.fitness))
{
for(j=0;j<lchrom;j++)
panduan[j]=rnd(0,1);
//for(j=0;j<lchrom;j++)////////////////
// {
// cout<<panduan[j];/////////////
// }
// cout<<endl;////////////////
// system("pause");////////////////
for(j=0;j<lchrom;j++)
{
if(panduan[j]==1)
child1.chrom[j]=parent1.chrom[j];
else
child1.chrom[j]=parent2.chrom[j];
}
for(j=0;j<lchrom;j++)
{
if(panduan[j]==0)
child2.chrom[j]=parent1.chrom[j];
else
child2.chrom[j]=parent2.chrom[j];
}
//for(j=0;j<lchrom;j++)////////////////
//{
// cout<<child1.chrom[j];/////////////
// }
//cout<<endl;////////////////
// system("pause");////////////////
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panduan;
}
else
{
for(j=0;j<lchrom;j++)
{
child1.chrom[j]=parent1.chrom[j];
child2.chrom[j]=parent2.chrom[j];
}
child1.geti=yima(child1.chrom);
child2.geti=yima(child2.chrom);
delete [] child2.chrom;
delete [] child1.chrom;
delete [] parent2.chrom;
delete [] parent1.chrom;
delete [] panduan;
}
}
void bianyi(individual &child)//变异
{
child.chrom=new unsigned[lchrom];
//cout<<"变异"<<endl;
bianma(child.geti,child.chrom);
for(int i=0;i<lchrom;i++)
if(flipm(child.fitness))
{
if(child.chrom[i]=0)
child.chrom[i]=1;
else
child.chrom[i]=0;
}
child.geti=yima(child.chrom);
delete [] child.chrom;
}
void bianma(double bianliang,unsigned *p)//编码
{
unsigned *q;
unsigned *gray;
q=new unsigned[lchrom];
gray=new unsigned[lchrom];
int x=0;
int i=0,j=0;
if(bianliang<zuobianjie)///////////////////
{
cout<<"bianliang:"<<bianliang<<endl;/////////
system("pause");
}
//cout<<youbianjie-(zuobianjie)<<endl;
//system("pause");
x=(bianliang-(zuobianjie))*((pow(2,lchrom)-1)/(youbianjie-(zuobianjie)));
//cout<<x<<endl;///////////
if(x<0)
system("pause");///////////
for(i=0;i<lchrom;i++)
{
q[i]=0;
p[i]=0;
}
i=0;
while (x!=0&&(i!=lchrom))
{
q[i]=(unsigned)(x%2);
x=x/2;
i++;
}
// for(i=0;i<lchrom;i++)//////////////////
// cout<<q[i];///////////////
// cout<<endl;///////////
int w=lchrom-1;
if(q[w]!=0&&q[w]!=1)
system("pause");
for(j=0;j<lchrom&&w>0;j++)
{
p[j]=q[w];
w--;
}
//cout<<"yuanma"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
gray[0]=p[0];
for(j=1;j<lchrom;j++)
{
if(p[j-1]==p[j])
gray[j]=0;
else if(p[j-1]!=p[j])
gray[j]=1;
}
for(j=0;j<lchrom;j++)
p[j]=gray[j];
//cout<<"geleima"<<endl;
//for(j=0;j<lchrom;j++)///////////
// cout<<p[j];////////
//cout<<endl;////////////////////
//system("pause");///////////
delete [] gray;
delete [] q;
}
double yima(unsigned *p) //译码
{
int i=0;
// for(i=0;i<lchrom;i++)/////////
// {
// cout<<p[i];//////
// }
// cout<<endl;/////////
// system("pause");//////////
int x=0;
unsigned *q;
q=new unsigned[lchrom];
q[0]=p[0];
// cout<<q[0]<<endl;//////////////////
// system("pause");//////////
for(int j=1;j<lchrom;j++)
{
if(q[j-1]==p[j])
q[j]=0;
else if(q[j-1]!=p[j])
q[j]=1;
}
// for(i=0;i<lchrom;i++)//////
// {
// cout<<q[i];//////////
// if(q[i]!=0&&q[i]!=1)
// {
// cout<<q[i];
// system("pause");
// }
// }
// cout<<endl;////////
// system("pause");///////////////////
for(i=0;i<lchrom;i++)
x=x+q[i]*pow(2,(lchrom-i-1));
if(x<0)
{
cout<<"译码出错1"<<endl;
system("pause");
}
//cout<<"x:"<<x<<endl;
double bianliang;
//cout<<pow(2,)<<endl;
//cout<<*x<<endl;
//cout<<(x*(/(pow(2,)-1)))<<endl;
bianliang=(x*((youbianjie-(zuobianjie))/(pow(2,lchrom)-1)))+zuobianjie;
if(bianliang<zuobianjie)
{
cout<<"译码出错2"<<endl;
system("pause");
}
delete [] q;
return bianliang;
}
double ran1(long *idum)
{
int j;
long k;
static long idum2=;
static long iy=0;
static long iv[NTAB];
float temp;
if (*idum <= 0)
{
if (-(*idum) < 1) *idum=1;
else *idum = -(*idum);
idum2=(*idum);
for (j=NTAB+7;j>=0;j--)
{
k=(*idum)/IQ1;
*idum=IA1*(*idum-k*IQ1)-k*IR1;
if (*idum < 0) *idum += IM1;
if (j < NTAB) iv[j] = *idum;
}
iy=iv[0];
}
k=(*idum)/IQ1;
*idum=IA1*(*idum-k*IQ1)-k*IR1;
if (*idum < 0) *idum += IM1;
k=idum2/IQ2;
idum2=IA2*(idum2-k*IQ2)-k*IR2;
if (idum2 < 0) idum2 += IM2;
j=iy/NDIV;
iy=iv[j]-idum2;
iv[j] = *idum;
if (iy < 1) iy += IMM1;
if ((temp=AM*iy) > RNMX) return RNMX;
else return temp;
}
double suijibianli()//随机遍历
{
double i=ran1(a);
while(i>zhizhenjuli)
{
i=ran1(a);
}
//cout<<i<<endl;//////////////
return i;
}
int fuzhi(float p)//复制
{
int i;
double sum=0;
if(sumfitness!=0)
{
for(i=0;(sum<p)&&(i<zhongqunshu);i++)
sum+=nowpop[i].fitness/sumfitness;
}
else
i=rnd(1,zhongqunshu1);
return(i-1);
}
int rnd(int low, int high) /*在整数low和high之间产生一个随机整数*/
{
int i;
if(low >= high)
i = low;
else
{
i =(int)((ran1(a) * (high - low + 1)) + low);
if(i > high) i = high;
}
return(i);
}
int flipc(double p,double q)//判断是否交叉
{
double pc1=0.9,pc2=0.6;
if((p-q)>0)
{
if(p>=avefitness)
{
pc=pc1-(pc1-pc2)*(p-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
else
{
if(q>=avefitness)
{
pc=pc1-(pc1-pc2)*(q-avefitness)/(maxfitness-avefitness);
}
else
pc=pc1;
}
if(ran1(a)<=pc)
return(1);
else
return(0);
}
int flipm(double p)//判断是否变异
{
double pm1=0.,pm2=0.;
if(p>=avefitness)
{
pm=(pm1-(pm1-pm2)*(maxfitness-p)/(maxfitness-avefitness));
}
else
pm=pm1;
if(ran1(a)<=pm)
return(1);
else
return(0);
}
void glp(int n,int s,int *h,int (*q)[1],float (*xx)[1])//glp
{
int i=0,j=0;
//求解q
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(q+i)+j)=((i+1)*(*(h+j)))%n;
}
}
i=n-1;
for(j=0;j<s;j++)
{
*(*(q+i)+j)=n;
}
//求解x
for(i=0;i<n;i++)
{
for(j=0;j<s;j++)
{
*(*(xx+i)+j)=(float)(2*(*(*(q+i)+j))-1)/(2*n);
}
}
}
BOOL Exist(int Val, int Num, int *Array)//判断一个数是否在一个数组的前Num个数中
{
BOOL FLAG = FALSE;
int i;
for (i=0; i<Num; i++)
if (Val == *(Array + i))
{
FLAG = TRUE;
break;
}
return FLAG;
}
python基础教程(代码编程教学入门)
python入门教程?
给大家整理的这套python学习路线图,按照此教程一步步的学习来,肯定会对python有更深刻的认识。或许可以喜欢上python这个易学,精简,开源的语言。此套教程,不但有视频教程,还有源码分享,让大家能真正打开python的大门,进入这个领域。gogui源码现在互联网巨头,都已经转投到人工智能领域,而人工智能最好的编程语言就是python,未来前景显而易见。黑马程序员是国内最早开设人工智能的机构。
一、首先先推荐一个教程
8天深入理解python教程:
主要讲解,python开发环境的构建,基础的数据类型,字符串如何处理等简单的入门级教程。
二、第二个教程,是系统的基础知识,学习周期大概一个月左右的时间,根据自己的学习能力吸收能力来定。初学者只要跟着此套教程学习,入门完全没有问题。
学完后可掌握的核心能力
1、掌握基本的Linux系统操作;
2、掌握Python基础编程语法;
3、建立起编程思维和面向对象思想;
可解决的现实问题:
字符串排序,切割,逆置;猜数字、飞机大战游戏;
市场价值:
具备编程思维,掌握Python基本语法,能开发出一些小游戏
所涉及知识点:
教程地址:
三、拓展教程
1、网络爬虫-利用python实现爬取网页神技
第一天:
第二天:
2、busmaster 源码Python之web开发利刃
第一天:
第二天:
3、python之大数据开发奇兵
python基础教程
运算
a=
b=
c=0
c=a+b
print"1-c的值为:",c
c=a-b
print"2-c的值为:",c
c=a*b
print"3-c的值为:",c
c=a/b
print"4-c的值为:",c
c=a%b
print"5-c的值为:",c
a=2
b=3
c=a**b
print"6-c的值为:",c
a=
b=5
c=a//b
print"7-c的值为:",c
python比较
a=
b=
c=0
if(a==b):
print"1-a等于b"
else:
print"1-a不等于b"
if(a!=b):
print"2-a不等于b"
else:
print"2-a等于b"
if(ab):
print"3-a不等于b"
else:
print"3-a等于b"
if(ab):
print"4-a小于b"
else:
print"4-a大于等于b"
if(ab):
print"5-a大于b"
else:
print"5-a小于等于b"
a=5
b=
if(a=b):
print"6-a小于等于b"
else:
print"6-a大于b"
if(b=a):
print"7-b大于等于a"
else:
print"7-b小于a"
赋值
a=
b=
c=0
c=a+b
print"1-c的值为:",c
c+=a
print"2-c的值为:",c
c*=a
print"3-c的值为:",c
c/=a
print"4-c的值为:",c
c=2
c%=a
print"5-c的值为:",c
c**=a
print"6-c的值为:",c
c//=a
print"7-c的值为:",c
逻辑运算符:
a=
b=
if(aandb):
print"1-变量a和b都为true"
else:
print"1-变量a和b有一个不为true"
if(aorb):
print"2-变量a和b都为true,或其中一个变量为true"
else:
print"2-变量a和b都不为true"
a=0
if(aandb):
print"3-变量a和b都为true"
else:
print"3-变量a和b有一个不为true"
if(aorb):
print"4-变量a和b都为true,或其中一个变量为true"
else:
print"4-变量a和b都不为true"
ifnot(aandb):
print"5-变量a和b都为false,或其中一个变量为false"
else:
print"5-变量a和b都为true"
in,notin
a=
b=
list=[1,2,3,4,5];
if(ainlist):
print"1-变量a在给定的列表中list中"
else:
print"1-变量a不在给定的列表中list中"
if(bnotinlist):
print"2-变量b不在给定的列表中list中"
else:
print"2-变量b在给定的列表中list中"
a=2
if(ainlist):
print"3-变量a在给定的列表中list中"
else:
print"3-变量a不在给定的列表中list中"
条件
flag=False
name='luren'
ifname=='python':#判断变量否为'python'
flag=True#条件成立时设置标志为真
print'welcomeboss'#并输出欢迎信息
else:
printname
num=5
ifnum==3:#判断num的值
print'boss'
elifnum==2:
print'user'
elifnum==1:
print'worker'
elifnum0:#值小于零时输出
print'error'
else:
print'roadman'#条件均不成立时输出
循环语句:
count=0
while(count9):
print'Thecountis:',count
count=count+1
print"Goodbye!"
i=1
whilei:
i+=1
ifi%:#非双数时跳过输出
continue
printi#输出双数2、4、6、8、
i=1
while1:#循环条件为1必定成立
printi#输出1~
i+=1
ifi:#当i大于时跳出循环
break
forletterin'Python':#第一个实例
print'当前字母:',letter
fruits=['banana','apple','mango']
forfruitinfruits:#第二个实例
print'当前水果:',fruit
print"Goodbye!"
获取用户输入:raw_input
var=1
whilevar==1:#该条件永远为true,循环将无限执行下去
num=raw_input("Enteranumber:")
print"Youentered:",num
print"Goodbye!"
range,len
fruits=['banana','apple','mango']
forindexinrange(len(fruits)):
print'当前水果:',fruits[index]
print"Goodbye!"
python数学函数:
abs,cell,cmp,exp,fabs,floor,log,log,max,min,mod,pow,round,sqrt
randrange
访问字符串的值
var1='HelloWorld!'
var2="PythonRunoob"
print"var1[0]:",var1[0]
print"var2[1:5]:",var2[1:5]
转义字符
格式化输出
print"Mynameis%sandweightis%dkg!"%('Zara',)
字符串函数:
添加元素
list=[]##空列表
list.append('Google')##使用append()添加元素
list.append('Runoob')
printlist
删除元素
list1=['physics','chemistry',,]
printlist1
dellist1[2]
print"Afterdeletingvalueatindex2:"
printlist1
列表操作
列表方法
删除字典
dict={ 'Name':'Zara','Age':7,'Class':'First'};
deldict['Name'];#删除键是'Name'的条目
dict.clear();#清空词典所有条目
deldict;#删除词典
print"dict['Age']:",dict['Age'];
print"dict['School']:",dict['School'];
字典的函数:
当前时间戳:
importtime
time.time()
格式化日期输出
importtime
printtime.strftime("%Y-%m-%d%H:%M:%S",time.localtime())
printtime.strftime("%a%b%d%H:%M:%S%Y",time.localtime())
a="SatMar::"
printtime.mktime(time.strptime(a,"%a%b%d%H:%M:%S%Y"))
获取某个月日历:calendar
importcalendar
cal=calendar.month(,1)
print"以下输出年1月份的日历:"
printcal
当前日期和时间
importdatetime
i=datetime.datetime.now()
print("当前的日期和时间是%s"%i)
print("ISO格式的日期和时间是%s"%i.isoformat())
print("当前的年份是%s"%i.year)
print("当前的月份是%s"%i.month)
print("当前的日期是%s"%i.day)
print("dd/mm/yyyy格式是%s/%s/%s"%(i.day,i.month,i.year))
print("当前小时是%s"%i.hour)
print("当前分钟是%s"%i.minute)
print("当前秒是%s"%i.second)
不定长参数:
*lambda:匿名函数
def....
python模块搜索路径
获取用户输入
str=raw_input("请输入:")
print"你输入的内容是:",str
input可以接收表达式
open参数
write要自己添加换行符
读取个字符
重命名:os.rename
os.remove
os.mkdiros.chdir
os.getcwd
os.rmdir
open参数
file的方法
异常:
try:
fh=open("testfile","w")
fh.write("这是一个测试文件,用于测试异常!!")
exceptIOError:
print"Error:没有找到文件或读取文件失败"
else:
print"内容写入文件成功"
fh.close()
try:
fh=open("testfile","w")
fh.write("这是一个测试文件,用于测试异常!!")
finally:
print"Error:没有找到文件或读取文件失败"
用户自定义异常:
os模块提供了非常丰富的方法用来处理文件和目录。常用的方法如下表所示:
|序号|方法及描述|
|1|
os.access(path,mode)
检验权限模式|
|2|
os.chdir(path)
改变当前工作目录|
|3|
os.chflags(path,flags)
设置路径的标记为数字标记。|
|4|
os.chmod(path,mode)
更改权限|
|5|
os.chown(path,uid,gid)
更改文件所有者|
|6|
os.chroot(path)
改变当前进程的根目录|
|7|
os.close(fd)
关闭文件描述符fd|
|8|
os.closerange(fd_low,fd_high)
关闭所有文件描述符,从fd_low(包含)到fd_high(不包含),错误会忽略|
|9|
os.dup(fd)
复制文件描述符fd|
||
os.dup2(fd,fd2)
将一个文件描述符fd复制到另一个fd2|
||
os.fchdir(fd)
通过文件描述符改变当前工作目录|
||
os.fchmod(fd,mode)
改变一个文件的访问权限,该文件由参数fd指定,参数mode是Unix下的文件访问权限。|
||
os.fchown(fd,uid,gid)
修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定。|
||
os.fdatasync(fd)
强制将文件写入磁盘,该文件由文件描述符fd指定,但是不强制更新文件的状态信息。|
||
os.fdopen(fd[,mode[,bufsize]])
通过文件描述符fd创建一个文件对象,并返回这个文件对象|
||
os.fpathconf(fd,name)
返回一个打开的文件的系统配置信息。name为检索的系统配置的值,它也许是一个定义系统值的字符串,这些名字在很多标准中指定(POSIX.1,5438源码Unix,Unix,和其它)。|
||
os.fstat(fd)
返回文件描述符fd的状态,像stat()。|
||
os.fstatvfs(fd)
返回包含文件描述符fd的文件的文件系统的信息,像statvfs()|
||
os.fsync(fd)
强制将文件描述符为fd的文件写入硬盘。|
||
os.ftruncate(fd,length)
裁剪文件描述符fd对应的文件,所以它最大不能超过文件大小。|
||
os.getcwd()
返回当前工作目录|
||
os.getcwdu()
返回一个当前工作目录的Unicode对象|
||
os.isatty(fd)
如果文件描述符fd是打开的,同时与tty(-like)设备相连,则返回true,否则False。|
||
os.lchflags(path,flags)
设置路径的标记为数字标记,类似chflags(),但是没有软链接|
||
os.lchmod(path,mode)
修改连接文件权限|
||
os.lchown(path,uid,gid)
更改文件所有者,类似chown,但是不追踪链接。|
||
os.link(src,dst)
创建硬链接,名为参数dst,指向参数src|
||
os.listdir(path)
返回path指定的文件夹包含的文件或文件夹的名字的列表。|
||
os.lseek(fd,pos,how)
设置文件描述符fd当前位置为pos,how方式修改:SEEK_SET或者0设置从文件开始的计算的pos;SEEK_CUR或者1则从当前位置计算;os.SEEK_END或者2则从文件尾部开始.在unix,Windows中有效|
||
os.lstat(path)
像stat(),但是没有软链接|
||
os.major(device)
从原始的设备号中提取设备major号码(使用stat中的st_dev或者st_rdevfield)。|
||
os.makedev(major,minor)
以major和minor设备号组成一个原始设备号|
||
os.makedirs(path[,mode])
递归文件夹创建函数。像mkdir(),但创建的所有intermediate-level文件夹需要包含子文件夹。|
||
os.minor(device)
从原始的设备号中提取设备minor号码(使用stat中的st_dev或者st_rdevfield)。|
||
os.mkdir(path[,mode])
以数字mode的mode创建一个名为path的文件夹.默认的mode是(八进制)。|
||
os.mkfifo(path[,mode])
创建命名管道,mode为数字,默认为(八进制)|
||
os.mknod(filename[,mode=,device])
创建一个名为filename文件系统节点(文件,设备特别文件或者命名pipe)。
|
||
os.open(file,flags[,mode])
打开一个文件,并且设置需要的treelab源码打开选项,mode参数是可选的|
||
os.openpty()
打开一个新的伪终端对。返回pty和tty的文件描述符。|
||
os.pathconf(path,name)
返回相关文件的系统配置信息。|
||
os.pipe()
创建一个管道.返回一对文件描述符(r,w)分别为读和写|
||
os.popen(command[,mode[,bufsize]])
从一个command打开一个管道|
||
os.read(fd,n)
从文件描述符fd中读取最多n个字节,返回包含读取字节的字符串,文件描述符fd对应文件已达到结尾,返回一个空字符串。|
||
os.readlink(path)
返回软链接所指向的文件|
||
os.remove(path)
删除路径为path的文件。如果path是一个文件夹,将抛出OSError;查看下面的rmdir()删除一个directory。|
||
os.removedirs(path)
递归删除目录。|
||
os.rename(src,dst)
重命名文件或目录,从src到dst|
||
os.renames(old,new)
递归地对目录进行更名,也可以对文件进行更名。|
||
os.rmdir(path)
删除path指定的空目录,如果目录非空,则抛出一个OSError异常。|
||
os.stat(path)
获取path指定的
statfs系统调用
系统调用:获取文件系统统计信息 - statfs与fstatfs statfs系统调用的主要目的是从已装载的文件系统中获取相关信息,通过指定路径,如"/"代表任何文件所在的文件系统。这个调用需要一个指向statfs结构的指针,该结构包含了如下的关键信息:文件系统类型:这些MAGIC常量定义在/usr/include/linux/magic.h中,部分在内核源代码中硬编码。
f_flags:位掩码,指示文件系统挂载选项,如ST_MANDLOCK(强制锁定)、ST_NOATIME(不更新访问时间)、ST_NODEV(禁止设备文件访问)等。
其他选项如ST_RDONLY(只读)、ST_SYNCHRONOUS(写入同步)等。
调用成功时返回零,失败时返回-1并设置相应的错误代码,如EACCES(权限拒绝)、EBADF(无效描述符)、EFAULT(无效地址)等。 需要注意的是,Linux的statfs和fstatfs系统调用与4.4BSD有所不同,且在处理大文件时引入了statfs和fstatfs。另外,LSB不推荐使用库调用statfs和fstatfs,推荐使用statvfs和fstatvfs。关于f_fsid字段,不同操作系统有不同的处理方式,如Solaris、Irix和POSIX使用unsigned long的f_fsid,而Linux和FreeBSD则使用fsid_t结构。 最后,statfs和fstatfs在某些情况下可能会遇到bug,例如在Linux 2.6.至3.1期间,由pipe创建的文件描述符执行fstatfs时可能会返回ENOSYS错误。 欲了解更多详细信息,可查阅stat(2)、statvfs(2)和path_resolution(7)。runc hang 导致 Kubernetes 节点 NotReady
Kubernetes 1..3 OS: CentOS 7.9. Kernel: 5.4.-1.el7.elrepo.x_ Docker: ..6
线上告警提示集群中存在 2-3 个 K8s 节点处于 NotReady 的状态,并且 NotReady 状态一直持续。问题的解决可以通过两种方法,我们先来看看 A 方案。
针对 docker hang 住这样的现象,通过搜索资料后发现了以下两篇文章里也遇到了相似的问题。这两篇文章都提到了是由于 pipe 容量不够导致 runc init 往 pipe 写入卡住了,将 /proc/sys/fs/pipe-user-pages-soft 的限制放开,就能解决问题。查看问题主机上 /proc/sys/fs/pipe-user-pages-soft 设置的是 。所以将它放大 倍 echo > /proc/sys/fs/pipe-user-pages-soft,然而 kubelet 还是没有恢复正常,pleg 报错日志还在持续,runc init 程序也没有退出。考虑到 runc init 是 kubelet 调用 CRI 接口创建的,可能需要将 runc init 退出才能使 kubelet 退出。通过文章中的说明,只需要将对应的 pipe 中的内容读取掉,runc init 就能退出。尝试了几个后,runc init 果然退出了。再次检查,节点状态切换成 Ready,pleg 报错日志也消失了,观察一天也没有出现节点 NotReady 的情况,问题(临时)解决。
对解决方案 A 的疑问,虽然问题解决了,但是仔细读 /proc/sys/fs/pipe-user-pages-soft 参数的说明文档,发现这个参数跟本次问题的根本原因不太对得上。pipe-user-pages-soft 含义是对没有 CAP_SYS_RESOURCE CAP_SYS_ADMIN 权限的用户使用 pipe 容量大小做出限制,默认最多只能使用 个 pipe,一个 pipe 容量大小为 k。这里就有疑问:为什么容器 root 用户 pipe 容量会超过限制。
定位问题最直接的方法,就是阅读源码。先查看下 Linux 内核跟 pipe-user-pages-soft 相关的代码。线上内核版本为 5.4.-1,切换到对应的版本进行检索。在创建 pipe 时,内核会通过 too_many_pipe_buffers_soft 检查是否超过当前用户可使用 pipe 容量大小。如果发现已经超过,则将容量大小从 个 PAGE_SIZE 调整成 2 个 PAGE_SIZE。通过机器上执行 getconf PAGESIZE 可以获取到 PAGESIZE 是 字节,也就是说正常情况下 pipe 大小为 字节,但是由于超过限制,pipe 大小被调整成 字节,这就有可能出现数据无法一次性写入 pipe 的问题。
找到问题根本原因的第一步,往往是在线下环境复现问题。由于线上环境已经通过方案 A 做了紧急修复,因此,需要找到一种必现的手段。功夫不负有心人,在 issue 中找到了相同的问题,并且可以通过以下方法复现。执行命令之后,立刻就出现 runc init 卡住的情况。通过 lsof -p 查看 runc init 打开的文件句柄情况,可以看到 fd4、fd5、fd6 都是 pipe 类型,其中,fd4 和 fd6 编号都是 ,是同一个 pipe。如何来获取 pipe 大小来实际验证下「疑问 2」中的猜想呢?Linux 下没有现成的工具可以获取 pipe 大小,但是内核开放了系统调用 fcntl(fd, F_GETPIPE_SZ)可以获取到,代码如下。编译好之后,查看 pipe 大小情况如下。重点看下 fd4 和 fd6,两个句柄对应的是同一个 pipe,获取到的容量大小是 = 2 * PAGESIZE。所以的确是因为 pipe 超过软限制导致 pipe 容量被调整成了 2 * PAGESIZE。
对解决方案 A 疑问的探索,对解决方案 B 的考虑,线上应该如何做修复呢?是否需要把 docker 所有组件都升级呢?如果把 dockerd/containerd/runc 等组件都升级的话,就需要将业务切走然后才能升级,整个过程相对比较复杂,并且风险较高。因此考虑是否可以单独升级 runc?因为在 Kubernetes v1. 版本中还没有弃用 dockershim,因此运行容器整个调用链为:kubelet → dockerd → containerd → containerd-shim → runc → container。不同于 dockerd/containerd 是后台运行的服务端,containerd-shim 调用 runc,实际是调用了 runc 二进制来启动容器。因此,只需要升级 runc,对于新创建的容器,就会使用新版本的 runc 来运行容器。
通过测试环境验证,的确不会出现 runc init 卡住的情况了。最终,逐步将线上 runc 升级成 v1.1.1,并将 /proc/sys/fs/pipe-user-pages-soft 调整回原默认值。runc hang 住的问题圆满解决。
总结,本次故障的原因是,操作系统对 pipe-user-pages-soft 有软限制,但是由于容器 root 用户的 UID 与宿主机一致都是 0,内核统计 pipe 使用量时没有做区分,导致当 UID 为 0 的用户 pipe 使用量超过软限制后,新分配的 pipe 容量会变小。而 runc 1.0.0-rc 正好会因为 pipe 容量太小,导致数据无法完整写入,写入阻塞,进而 runc init 卡住,kubelet pleg 状态异常,节点 NotReady。修复方案是 runc 通过 goroutine 及时读取 pipe 内容,防止写入阻塞。