【自动化运维新手村】Python基础-2_EthanYue1024的博客-程序员资料

技术标签: python  运维  Python玩转自动化运维  自动化  

摘要

首先说明,以下几类读者请自行对号入座:

  • 对CMDB很了解但对于Python还没有上手的读者,强烈建议阅读前面几篇;
  • 对Python了解较少只能写出简单脚本的读者,强烈建议阅读此篇;
  • 已经可以熟练写出Python脚本,但对CMDB不是很了解的读者,建议阅读此篇;
  • 即了解Python,又了解CMDB的读者,可以出门左转,看下一篇。

上一节我们简单地阅读了CMDBv1.0.py的源码,了解到其基本的模块构成,并且结合实际的程序理解了Python的常用数据结构以及基本的条件语句与循环语句的运用。那么这一节我们将详细阅读每一个模块的代码,并将其所涉及的知识点拆解开来,帮助各位读者更快的进入到Python的世界。

为什么要阅读源码

在开始之前我想向大家说明的是,之所以才在第三节就带领大家深入到源码中去,是因为Python作为最易上手的解释型语言,其社区生态和包含的各种第三方库数不胜数,而且任何一门语言其内置的规范和方法对于初学者来说都无法穷尽,所以如果一点儿一点儿的去学习某个内置方法,某个包如何使用,在我看来其实是本末倒置的,任何在没有使用场景的情况下进行填鸭式的灌输内容,都是”耍流氓“

比如大家其他新手教程里十分常见的读写文件功能,说实话读写文件也就是一两行代码可以完成的事情,但哪怕你看过无数次如何读写文件,到了真正需要用它的时候,都是一脸懵"x"的,你只能模糊的记得好像学到过,但就是无法下手,本质上是因为你没有真正的场景去用它,对于刚接触编程的读者来说,一些简单的示例,无法在脑海中构建起一个完整的程序,这也是我刚开始就带领大家由浅入深去接触源码的原因

首先这里的源码是对于我们运维人来说都熟知的CMDB的基本功能,大家在了解其功能的情况下,去思考如果这个代码是你写的,你会如何去实现这个CMDB基本的增删改查,然后在我们一起阅读源码的过程中,你会发现真正实现这些功能的过程是怎样的,慢慢去深入到具体的细节又该如何编写代码,这其实就是一个编程的思维,我们学任何一门语言,都不止是单纯的为了去学会它,然后用它,而是要了解面对一个大问题时候用编程去解决他的思维逻辑,这也就是为什么一些计算机专业毕业的同学,可以快速应对很多新技术的变迁。所以希望大家在阅读源码前能够有这样的认知,并且带着思考去一起学习。

CMDBv1.0.py伪代码

首先我们先再熟悉一下CMDBv1.0.py的伪代码

def get():
    查询内容

def update():
    修改内容
    
def delete():
    删除内容
    
def init():
	初始化信息
    
def add():
    添加内容

if __name__ == "__main__":
    通过命令行参数执行对应的操作

阅读源码前的思考

上面说到希望读者们在阅读源码前要带着思考,这里的思考准确的就说,如果是你,你会如何去设计并且实现所需要的功能,虽然你不知道具体的代码如何写出来,但起码要去思考每一步应该怎么做,对于一些刚接触编程的读者,一开始就由我先来带着大家思考。

很多人一看到我们第一节中演示的功能时就已经懵了,内心os:”这么多复杂的步骤我从哪儿下手呢,根本毫无头绪“。那么其实我们的CMDBv1.0最主要的功能就是增删改查,具体的代码就应该是分别去实现增删改查四个不同的功能,然后在不同的情况下去使用这些功能就好了,这种思考貌似听起来是废话,但其实不然。如果你真的能够像我描述的这样思考,那恭喜你,其实你已经算是迈出了一大步,已经具备了将一个大问题去拆解成小问题的能力;如果你能再将其落地成我上述的伪代码形式,那么再次恭喜你,你已经具备了从一行行的脚本代码跨越到函数式编程的能力。

一开始不具备这种思维方式很正常,现在我已经向你演示了如何去分析拆解一个场景,那么接下来我们就继续深入,看看每一个步骤都是如何实现的。

上源码

初始化地域信息

一般对于运维资产的维护中,最顶层的是地域,也就是说我的设备是放在哪里的,那么我们CMDB如果需要录入设备信息之前,就必须要先初始化数据,那么初始化地域的代码如下:

import json
def init(region):
    data[region] = {
    "idc": region, "switch": {
    }, "router": {
    }}
    print(json.dumps(data, indent=2))

我们定义了一个函数叫做init,而这个函数需要传入一个region名称作为参数,这里的region其实就相当于我们的地域,我们此处假设一个region只有一个idc机房,那么我们需要初始化的数据格式如下:

data = {
    
    "region名称": {
    
        "idc": "region名称",
        "switch": {
    },
        "router": {
    } 
	}
}
// 这个数据的格式表示的含义就是我有一个总的数据源data,它下面可以存储某个region的信息,
//而这个region内包含了一个idc名称,和switch以及router信息,switch和router信息呢,
//又都是字典,我们后续就可以将具体的设备详情存储进去。

而根据我们第一节课对于Python基本数据类型的学习来看,我们的数据源data是一个字典,那么给字典赋值的操作如下:

data[region] = {
    "idc": region, "switch": {
    }, "router": {
    }}

我们初始化好数据之后,肯定想将其打印出来看一看,那么可以使用print(data)将数据打印出来,但此处我们的data是一个字典,直接进行打印的结果可能像是如下这样:

{"region": {"idc": "region", "switch": {}, "router": {}}}

这种格式当数据越来越多的话就会很难阅读,所以我们利用到了一个Python的内置库json

Tips:json库解读

Json(JavaScript Object Notation 的缩写)是一种数据交换格式,最常用于客户端-服务器通信;当然你也可以将它保存到本地,所以也可以用来作为配置文件;Json 很像 Python 中的字典,但Json本质上是一种字符串,所以在Python中需要利用其内置库 json,来实现Json字符串和字典的转换。

最常用的将Python中的字典与Json字符串进行转换的两个方法是

data = json.loads(data_str)  # 将json字符串转为字典
data_str = json.dumps(data)  # 将字典转为json字符串

代码中是将字典转为字符串之后打印出来,但大家注意代码中的写法是json.dumps(data, indent=2),这时因为json.dumps可以传入很多参数,如下:

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding="utf-8", default=None, sort_keys=False, **kw)

无论对于Python的内置方法时候第三方库,我们在调用其方法的时候,都可以通过跳转的方式,去进入到其源码中去看到他的实现逻辑,这里最常做的就是去看这些方法的注释以及参数说明。

Tips: 常见的vscode或者Pycharm都可以通过快捷键的方式去进行跳转,windows可以按住Ctrl+单击即可跳转,mac的话按住command+单击即可跳转。

这里我们跳转到json.dumps方法中去看看它的参数注释,但我们本着没用到就先忽略的原则,我们只了解其中的indent参数即可,注释如下:

If ``indent`` is a non-negative integer, then JSON array elements and
object members will be pretty-printed with that indent level. An indent
level of 0 will only insert newlines. ``None`` is the most compact
representation.
友情翻译如下:如果indent是一个非负整数,那么JSON数组或者对象成员将会被带着缩进层级优雅的打印出来,一个为0的缩进只会插入换行符,而当其为None时,JSON只会被最紧凑的表示出来。

所以通过注释可以理解为,indent其实就是帮助我们将json字符串好看的打印出来的参数,只要是正整数即可,大家可以自己去尝试不同的正整数打印出的结果。

现在我们已经了解了如何初始化一个地域,并且将其信息打印出来,但有一点需要注意的是,当程序结束后,我们的数据源data就会消失,当我们下次再次运行程序时,我们的数据源data仍然时空的。这里就涉及到数据的持久化。

Tips:持久化

因为Python程序运行过程中定义的所有变量,都只会存在于程序运行时计算机为其分配的内存空间里,此处设计到计算机组成原理的相关知识,我们会在番外篇中提到。而持久化的含义就是将数据永久的保存在磁盘上,这样我们每次都可以从磁盘上去读取数据。

Python中持久化数据的方式有很多种,而且在实际的企业应用中,肯定是将这些数据保存在数据库中,但因为我们目前还没有涉及到数据库的知识,且数据量较小,我们就暂且将其保存在文本文件中即可。这里我们仍然通过Python内置的json库来做数据的持久化和读取。

json库中还有两个常见的方法是

data = json.load(f)  # 从文件中读取内容并转为字典
json.dumps(data, d)  # 将字典存到文件中
  • json数据的持久化如下
f = with open("data.json", "w+")
json.dump(data, f)
f.close
  • json数据的读取如下
f = open("data.json", "r+")
data = json.load(f)
f.close()

划重点
这里需要考虑一个特殊情况,当我们传入的region已经存在的时候会发生什么,比如有一个不太熟悉资产的同学使用了这个脚本,或者地域信息太多你自己也忘记已经存在哪些地域,那么这时候如果使用初始化功能去初始化一个已存在的地域时,这个地域的信息是不是就被清楚掉了,所以这里还需要补充一个判断条件

if region in data:
    print("region %s already exists" % region)
    return

这里用到了一个条件判断,可以直接用 if key in dict的方式去判断字典中是否已存在这个键,当存在时我们就打印提示信息,并直接通过return退出该函数。
这里还用到了格式化字符串的操作,当我们的一个字符串中某个值为变量时,我们可以用上面的方式去表达,这里的%s表示字符,与之对应的还有%d表示整数,%f表示浮点数等,具体的其他格式化方法我们会在番外篇中提到。

Tips: 函数返回值

Python中的函数必然存在返回值,返回值可以是一个,也可以是多个,当函数中没有任何return语句时,函数的返回值即为None,当我们想要在指定地方显示的退出函数时可以直接用return,这时函数的返回值也为None

当存在多个返回值时,可以直接使用return a, b,比如:

def foo():
    a = 1
    b = 2
    return a, b

res = foo()  # 这时的 res 值是一个元组类型, 输出结果为 (1, 2)
a, b = foo()  
# 这里是用到了Python中的解包写法,解包的写法可以运用于Python的任何可迭代对象,比如 
> my_list1 = [1, 2]
> a, b = my_list  # 最终的结果 a 为 1, b 为 2
# 所以 a, b = foo() 等价于 
res = foo()
a, b = res

所以CMDB初始化地域的完整代码如下:

def init(region):
    with open("data.json", "r+") as f:
        data = json.load(f)
    if region in data:
        print("region %s already exists in data" % region)
        return
    data[region] = {
    "idc": region, "switch": {
    }, "router": {
    }}
    with open("data.json", "w+") as f:
        json.dump(data, f)
    print(json.dumps(data, indent=2))

细心的读者可能会发现怎么持久化的操作不太一样,这里是用到了一个Python中的语法糖,with... as,这样可以在对文件进行操作时,可以避免最后手动执行f.close(),具体with...as的原理我们会在番外篇中提到,这里大家先记住即可。

那么我们对于源码的解读这一节就先到这里,我们这一节最主要的是需要去学习培养正确的编程思维,学会在阅读源码前如何思考,如何带着思考去拆解源码。后面的章节我们会继续阅读其他功能模块,带领大家更进一步的探索Python的世界。

篇后语

最近听到了一个词叫做”知识的诅咒“,含义大概是,当你对某一个知识了解较深时,就无法准确的向别人解释清楚这个知识,因为你总是假设别人也和你一样有相同的知识背景。所以我在向大家传递Python的相关知识的时候,我其实有在刻意的避开这种诅咒,我写这个系列的本意也是想让没有接触过编程的同学能够更为通俗易懂的了解编程,并且上手写出自己真正需要的代码。所以如果大家对于我的讲解顺序或者逻辑有什么疑问和建议,也欢迎提出。


欢迎大家添加我的个人公众号【Python玩转自动化运维】加入读者交流群,获取更多干货内容
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40489165/article/details/121759355

智能推荐

android 背景图缩放,解决android:background背景图片被拉伸问题_weixin_39639600的博客-程序员资料

ImageView中XML属性src和background的区别:background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸。src是图片内容(前景),bg是背景,可以同时使用。此外:scaleType只对src起作用;bg可设置透明度,比如在ImageButton中就可以用android:scaleType控制图片的缩放方式如上所述,backg...

qt用odbc连接mysql_【原创】Qt 使用ODBC driver 连接SQL Server_午餐时间到了的博客-程序员资料

最近在做数据库的课程设计。第一个需要解决的问题是使用什么工具来实现这个系统。经过一番资料查找,决定使用SQL Server Express 2012作为服务器,使用Qt作为编写客户端程序语言。问题是client如何连接SQL Server? 下面是我的解决方法。1.开启windows上的SQL Server 的ODBC驱动ODBC 是一个调用级接口,它使得应用程序得以访问任何具有 ODBC 驱动程...

翻页时钟代码大公开_lovefan的博客-程序员资料_翻页钟开源代码

不少朋友向我要翻页时钟的代码,现在贴给大家。代码水平有限,见谅。看不明白的可以问我:)js// miniprogram/pages/flipClock/jsconst moment = require('../../../utils/moment-with-locales.min.js');const Lunar = require('../../../utils/lunar.js');var startX, endX;var moveFlag = true; // 判断执行滑动事件.

JAVA切换不了FTP服务器目录_解决linux下ftp指定访问目录无法修改的问题_豪睿刘爱上楼楼梯的博客-程序员资料

他的系统是CentOS,是RH派系的。我把vsftpd安装配置好了,以为大功告成,但客户端访问提示如下错误:500 OOPS: cannot change directory:/home/ftp原因是他的CentOS系统安装了SELinux,因为默认下是没有开启FTP的支持,所以访问时都被阻止了。//查看SELinux设置# getsebool -a|grep ftpftpd_disable_tr...

.NET实现网络爬虫_hyunbar的博客-程序员资料_.net 爬虫

爬虫的特征和运行方式User-Agent:主要用来将我们的爬虫伪装成浏览器。Cookie:主要用来保存爬虫的登录状态。连接数:主要用来限制单台机器与服务端的连接数量。代理IP:主要用来伪装请求地址,提高单机并发数量。爬虫工作的方式可以归纳为两种:深度优先、广度优先。深度优先就是一个连接一个连接的向内爬,处理完成后再换一下一个连接,这种方式对于我们来说缺点很明显。 广度优先...

c web service_简单并快乐着的博客-程序员资料

转自 http://blog.163.com/wzbwzb_187/blog/static/6632425720106424158919/ 以下是源代码: /**************filename: Server.cpp**************** 该程序通过标准socket实现简单Http服务器 运行该服务器可以通过浏览器访问服务器目录下的 Html文件和j

随便推点

Bibtex格式类型_小王同学w的博客-程序员资料_bibtex类型

出于保留资源和查找方便,转载自https://blog.csdn.net/kmsj0x00/article/details/85318057类型简介必需关键字可省略关键字@article期刊或杂志上的一篇文章。author, title, journal, year.volume, number, pages, month, [email protected]有确定出版社的书籍。author或editor, title, publisher, year.volume或number, series, address, e

SpringBoot-Google二步验证_apkqfa6158的博客-程序员资料

SpringBoot-Google二步验证概念:Google身份验证器Google Authenticator是谷歌推出的基于时间的一次性密码(Time-based One-time Password,简称TOTP),只需要在手机上安装该APP,就可以生成一个随着时间变化的一次性密码,用于帐户验证。Google身份验证器是一款基于时间与哈希的一次性密码算法的两步验证软件令牌,此软件...

Maven_weixin_41249041的博客-程序员资料

maven帮助构建项目 项目和项目之间的依赖关系,管理jar包。项目管理工具,管理java项目:1、项目对象模型 POM对象模型,每个maven工程中都有一个pom.xml文件,定义工程所依赖的jar包、本工程的坐标、打包运行方式。。2、依赖管理系统(基础核心 )maven通过坐标对项目工程所依赖的jar包统一规范管理。3、maven定义一套项目生命周期清理、初始...

css教程系列5:px、em、rem区别介绍_邢晋宇的博客-程序员资料

1 PXpx像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。PX特点1. 浏览器无法调整px单位的字体,以em或rem为字体单位可调整字体。 2 EMem是相对长度单位。EM特点1. em的值并不是固定的;2. 行高:n倍的 em = n *父级元素的像素px大小(若无则*浏览器的默认字体)。3 REMrem是CSS3新增的一个相对单位(root em,根em),也是相对...

Matlab: 作图_weixin_34413357的博客-程序员资料

查看当前变量可以用who,查看当前变量及其结构,大小,类型等,可以用whos。控制图的大小figure(‘position’,[x0,y0,dx,dy]);figure(fig number);控制图例(legend)legend('leg1','leg2','Location','NorthWest');% hide the legend boxlegend boxoff...

CentOS7 安装 MYSQL5.6_LiexingVerne的博客-程序员资料

最近在学习虚拟机的下安装mysql,弄了很久最后终于搞好了(感觉自己太笨),记录下自己遇到的问题。环境:1.CentOS 7X642.mysql-5.6.45-linux-glibc2.12-x86_64.tar.gz安装步骤1.检查是否安装mariadbrpm -qa | grep mariadb如果存在就卸载rpm -e--nodeps mariadb...

推荐文章

热门文章

相关标签