分类目录归档:Python

关于Django学习的计划

各位小伙伴好,上周刚说到要开始我们的django学习之旅了,谁知上周公司业务调整,临时安排了很多工作,搞得天天加班到11点(夜里), 回到家累成狗,连按电脑开关的力气都没有了,  虽然上周身体比较累,但脑袋却没闲着,就构思了后续的学习计划, 因为吧写脚本跟写web平台差别还是非常大的,因为脚本都是单一性的任务或功能,但要做web运维平台它是一个综合性技术的体现,比如最基本的html你得懂,像html的基本的table, form、列表等在实际开发中用的非常的多,如果这个都不熟练,那越往后学难度会越大,在了解了html的基础上,css你要懂一点吧,不然列表菜单放左边还是放右边,站点导航栏怎么设置,页面背景用什么颜色,总不能一个站点就一个颜色吧,所以css可能不需要像专业前端一样,但最起码一些简单的设置你要必须懂,假设你这二项全部过关,你以为就OK了?NO,差的还很远, 因为我们不是专业设计,所以做出来的平台界面一定不美观,你懂的,现在做什么都讲究时尚炫酷(体现装逼的时刻),要想把自己的网站做的更专业一点,你怎能不去了解bootstrap?如果你已经能把bootstrap样式运用的炉火纯青,你这时候你就能完成一个看着比较专业的网站了,但是问题又来了,我需要在页面上加一些动态效果怎么办呢?那就得去学习javascript呀, 这玩意儿很厉害,js现在是搞前端的基本技能,不然都不好意思封自己为前端工程师,到这还没完,在实际开发中假设你数据库里已经存好了一些数据,你需要在前端页面实时把这些数据展现出来, 怎么办?那你得去学习AJAX呀,当然用JavaScript写一个完整的AJAX代码是可以的,但如果有更方便的做法,我们为没有理由不去选择,这时候就用到另一个东东了,它的名字就叫jquery了,写到这我们总结一下做一个web站点需要学习的内容: html,  css, bootstrap, javascript, jquery,   如果以上技术你都具备了,然后在加上我们的python + django,你基本就全能工程师了, 不,全能太俗了,他们的名字叫叫全栈工程师,英文名字是Full Stack developer,所以接下来我打算把这些内容逐步展开来写,但从哪个部分开始这个我可伤了脑筋,因为我不知道每个人的水平,苦想了半天,我还是觉得就从最基本的html说起吧,由浅入深逐步开始学习,这是正道儿,另外欢迎每个小伙伴给我留言探讨。

python基础17-并发编程(2)

上篇我们介绍了Python的多线程模式,也了解了在python中有GIL这么个东西,所以cpu密集型的程序在python中是无法实现真正并发的,因为实际执行的还的单个线程,可现在的服务器都至少是16核,那岂不浪费了, 所以如果我们想要重分利用cpu资源,我们就需要在Python中采用多进程模式,就是用进程的方式实现并发,在Python下实现多进行时用multiprocessing模块来实现,这个模块用法跟threading.Thread非常类似,但不同的时它没有GIL锁,可以在多核CPU机器上来实现真正的并发执行,关于进程线程概念就不多说了,上篇已经全部介绍了,这篇就直接就直接上代码了,代码是在上篇基础上进行的修改,如下:

从上面代码可以看到,在使用上真的非常像线程,而且大部分方法的功能也是一样的,这里是用Process创建进程对象,join()方法等待进程池中的全部进程,target我们给一个可调用对象,这是我认为最简答的方式,给了一个函数,函数内容还是上篇的内容我基本没动,一样运行没有任何问题。

上面这种方法我们已经实现了多进程,如果任务执行的对象不算太多是可以的,但如果任务时间比较长且操作对象比较多可能会出现进程占用系统资源过度造成服务器慢的情况,因为同时在机器上启动上百上千个进程,而且短时间任务执行不完,就会非常的耗系统资源,机器估计卡的用不了,怎么解决这种问题呢,这就需要用到我们的进程池了,使用Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,进程池的大小可以参考机器CPU核数来指定,那么这样一来,我们的代码需要修改如下:

可以看到我们使用了进行池,代码逻辑反而简单了,这里map函数跟python中内置的map功能一样,它需要2个参数,一个是函数,一个是序列,不同的是它可以支持多进程,这里我设定了5个进程,就是最多可以跑5个进程,这样一来就解决了我们上面提到的问题。

关于并发编程的内容就写这2篇了,随着这篇的结束,我觉得python的基础部分就要告一段了,当然如果在基础部分还有想了解的内容,可以后台留言给我,我会穿插到后续的文章中,另外如果小伙伴是一路跟过来的话,我相信你已经能熟练运用python来实现工作中的一些需求了,  但我们python的学习之路远不止如此,因为随着各个公司业务的复杂度提升,对运维人员技能要求也越来越高,如何快速完成需求,如何把运维繁杂的任务简单化,这可能是大多数公司运维要解决的问题,要达到这条路我个人觉得离不开web运维自动化平台,通过平台使我们运维的一些工作通过平台点几下鼠标就可以完成,所以我认为这才是我们的学习目标, 但要实现这个目标,就要进入我们下一个阶段的学习了,下个阶段我们主要介绍python web框架Django技术, 还清小伙伴多多支持(请戳右上角)。

python基础16-并发编程(1)

从这篇开始我们学习python并发编程的内容,之所以把并发编程放到最后去说,是因为并发编程涉及很多概念,还用到了类,跟之前的基础知识不同,不是几句话或者几行代码就能说清楚的,在我们正式写代码前我们先梳理下基本概念,然后再进入实际代码环节,因为要NB,不但要会写代码,而且还能理解代码背后的意义,if  赞同:   我们先来了解下进程和线程的历史:

我们都知道计算机是由硬件和软件组成的。硬件中的CPU是计算机的核心,它承担计算机的所有任务。 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配、任务的调度。 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等。 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专门的管理和控制执行程序的数据结构——进程控制块。 进程就是一个程序在一个数据集上的一次动态执行过程。 进程一般由程序、数据集、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成;数据集则是程序在执行过程中所需要使用的资源;进程控制块用来记录进程的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。

在早期的操作系统里,计算机只有一个核心,进程执行程序的最小单位,任务调度采用时间片轮转的抢占式方式进行进程调度。每个进程都有各自的一块独立的内存,保证进程彼此间的内存地址空间的隔离。 随着计算机技术的发展,进程出现了很多弊端,一是进程的创建、撤销和切换的开销比较大,二是由于对称多处理机(对称多处理机(SymmetricalMulti-Processing)又叫SMP,是指在一个计算机上汇集了一组处理器(多CPU),各CPU之间共享内存子系统以及总线结构)的出现,可以满足多个运行单位,而多进程并行开销过大。 这个时候就引入了线程的概念。 线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合 和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。 线程没有自己的系统资源,只拥有在运行时必不可少的资源。但线程可以与同属与同一进程的其他线程共享进程所拥有的其他资源。

以上这段来自互联网,关于进程和线程说的比较清晰,所以为了让大家更好的了解,我这边直接引用了,在了解了进程和线程后,我们再来看Python中的并发实现,不用想,Python中一定有这种类似模块,没错,这个模块就是threading,  不过学习Python的人都知道,在python中有这么一个玩意儿,叫GIL,中文名叫全局解释器锁,这个锁能保证同一个时刻只有一个线程在运行,这个就保证了在python内部是线程安全的,解决了线程间数据一致性和状态同步的困难,但问题来了,这问题就是你即使编写的多线程代码,运行时其实还是在单线程执行,没法实现真正的多线程,看到这些是不是心里哇凉哇凉的, 不过这些大家也不必过多担心,这里说的情况是CPU密集型的情况,如果是IO密集型的情况下是允许其它线程在这个线程等待I/O的时候运行的,所以结论是,Python的多线程在多核CPU上,IO密集型的程序能更适合利用多线程。

写到这,理论部分就完了,接下来进入我们代码实战阶段,我们从一个实际的运维工作例子中来,比如你们公司有100个站点需要维护(理论上可以测试更多数据,但为了更快演示我只选了100个),你需要定时检测这些站点是否可以正常访问,我们以此需求背景来完成这个代码例子,首先我们用常规方法编写代码,然后在用threading模块实现并发,然后对比看效果,代码如下:

判断一个站点是否正常,最常用的方法就是获得这个站点的http状态码,在这里我简化了需求,只把获得的状态码写入到了文件中, 如果要做监控可以读取这个文件,如果不是2xx或3xx的,就可以报警了,我们把要检查的站点写入urls.txt文件中,通过for循环,调用get_site_code()函数将获得的站点状态码写入site_stauts.txt文件中,加入time模块主要就是对比先后运行时间,运行结果:

执行完成一共花了17秒时间,接下来我们采用并发方式修改下这个执行代码,如下:

运行结果如下:

我们看只用了2秒,快了8倍,看完结果接下来我们说下代码,在这例子里我选择了我个人认为最简单的方法,就是在实例化每个Thread对象的时候传入了我们定义的函数get_site_code()和需要的参数url, 实例化后得到一个Thread的实例t,我们把这个t加入线程列表threads中,接下来循环这个列表开始调用start()函数去执行,除了start()函数,我们还用到了join()函数,这个函数允许主线程等待线程结束.

上面的方法没问题后,我们来看第二个实现方法,我们还可以通过继承父类 threading.Thread,来实现一个子类,通过实例化我们自己的子类来实现并发,这里我们需要注意的是run方法是父类的一个方法,我们在子类中重新了父类的run方法,代码实现如下:

这个脚本跟上面运行效果是一样的,但是通过继承父类的方式来实现的,关于类的继承上篇我们已经讲过了,在代码里我注释了一行,保留了子类继承父类的二种方式的写法,写到这,可能有的小伙伴要问,为什么要有这种方式实现呢?这是因为类对比函数来说可以实现更多更灵活的应用场景,比单纯的函数要强大,所以有时候必须要用这种方式去实现。

这篇就到这里, 在最后,我们回到前面我讲的GIL的问题,如果有的时候就需要用Python来实现利用多核CPU的情况怎么办,办法是有的,就是采用多进程方式,不过这就用到了multiprocessing模块,关于这个模块我们下篇再继续, 另外码字不易,感觉不错的小伙伴请点右上角帮忙转发,多谢。

python基础15-面向对象编程(3)

上篇我们说了类的基本概念,这篇我们谈谈类的一个很重要的概念-继承, 在工作中使用类继承非常常见,当我们编写一个类时并非每次都要从头实现一个类,如果你要实现的类在方法或属性另一个类里已经有了,这时候可以通过继承来自动 获得这个类的所有属性和方法,这个类就叫父类,继承父类的类我们叫子类,通过类的继承,可以让我们减少我们同一段代码要输入好几次的情况,Python允许子类继承多个父类,这种特性我们叫多重继承,这个不是python语言特性,c++也是一样,接下来让我们了解下如何通过代码的方式实现类的继承。

我们还用我们上次定义的Car类来说明继承关系, 代码如下:

这个类我加了一个方法,用来展示汽油用来信息, 现实中我们知道除了汽油,现在电动车也非常流行了,所以我们如果我们需要定义一个电动汽车的类,我们会发现同样在初始化类的时候也需要公司,品牌,生产时间必须的参数,因为这些信息在Car这个类在初始化的时候已经定义了,所以我们可以直接继承Car来实现我一个新的电动车的类,代码如下:

短短二行就实现了父类的继承,代码一会解释,主要是super函数,我们先看结果是否跟我们想的一样,因为根据继承的概念,如果子类继承了一个父类,就会获得父类所有的属性和方法,那接下来让我们看看是不是这样的:

打印出:

可以看到在我们子类Evcar中,我们并没有定义get_car_info这个方法,但我们一样可以直接使用,说明子类继承了父类的方法,直接调用了父类的方法打印了信息,这时候我们输出子类的__bases__属性(__bases__类属性包含了其父类的集合元组),如下:

显示父类是Car。

我们说回代码中的内容, 关于继承父类_方法,现在因为python版本出于2和3交替阶段,写法也有不同,汇总2个方法如下:

1、用super函数,这个函数的目的就是帮助程序员找出相应的父类,然后方便调用相关的属性和方法,在版本2中写法就是跟我上面的例子一样,在3中去掉了super函数中的2个参数,直接调用即可。

2、在子类中显示调用父类初始化,例如:上面的super函数行可以替换成这样:

上面我们了解到了子类和父类的概念,也了解了一个子类如何继承一个父类的属性和方法,接下来我们要看看如何覆盖父类的方法,那为什么要覆盖呢,因为有时候我们从父类中继承的一些方法,不一定能满足或适合子类使用,这时候子类就可以重新这个方法,来实现对父类方法的覆盖,例如我们的例子,petrol_used()这个方法显示不适合用在电动汽车上,那这时候我们可以在子类中重新这个方法,如下:

方法名词同父类相同, 这时候我们调用父类和子类同名的方法会得到如下信息:

从结果看子类的方法被运行了,实现了我们子类的方法覆盖了父类的方法。

关于类对基本内容就写到这里了,希望小伙伴们在了解了基本概念的基础上,多在项目中运用,逐步体会面向对象的编程思想,下篇我们谈一下python的并发编程,我们的基础内容就全部结束了,感谢大家支持。

 

python基础15-面向对象编程(2)

上篇我们介绍了Python面向对象编程的基本理论知识,这篇我们开始看如何实际定义类和如何调用类方法,在Python中定义类的关键字是class,我们就拿周边的事物说起,这样大家也比较容易理解,比如我们定义一个汽车类,如下:

以上代码我们定义了一个简单的汽车类,我们来逐行说明解释下代码, 大家知道def是用来定义一个函数的,那如果在类里定义一个函数,这个函数就称为方法,除了名字不同之外,我们之前学的关于函数的内容都适用于方法,所以在这里__init__()我们理解是一个函数,因为是在类中,所以我们叫它__init__()方法,如果是第一次接触,可能看着有点不习惯,因为这个方法前后都有二个下划线,跟我们平时看到的名称不大一样, 这种写法主要是避免Python默认方法跟自定义的方法发生冲突,所以我们可以不用管它形式,知道它本质就可以了,在Python中还有很多这种形式的特殊方法,另外__init__()方法也被称为构造器,它用于根据类的定义创建实例。

这里__init__()定义中包含四个形参,其它参数都容易理解,我们着重看第一个参数self,在Pythonl类中,self不可缺少,并且它必须放在其它参数前面,因为python在调用__init__()方法创建实例时,将自动传入实参self, self是类实例方法中引用方法所绑定的实例,它是指向实例本身的引用,让实例能够访问类中的属性和方法,当我们创建car实例时,我们只需要给后面三个参数就可以了,self因为会自动传递,所以我们不需要再传递。

接下来我们创建一个实例,看如何调用:

打印出:

我们创建一个实例my_car,  我们传递公司,品牌,时间参数, self我们并没有传递, 然后实例调用方法get_car_info()打印出了汽车实例的信息。

这个类基本是最简单的类了,大家看到在类中的方法都需要self参数,这种方法叫实例方法,在类中除了实例方法,还有一种叫静态方法,静态类方法无需传入self函数,但需要@staticmethod修饰,类和实例都可以访问静态方法。

以上我们拿生活的汽车来举例说明,在运维中的应用基本也是这个思路去实现,比如数据库类,我们可以在__init__()方法里把数据库的名称,IP,端口,数据库用户,密码等放到这个方法里,再定义一个方法根据这些去连接db,然后返回连接对象来对数据库进行操作,这个就是实现一个DB类的基本思路。

这篇我们就简单说一下类和实例内容,另外类会有父类、子类区分,那么关于子类和父类继承关系以及子类重写父类方法内容我们会放到下篇去介绍, 下篇见~