【自动化运维新手村】Python基础-2

摘要

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

  • 对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玩转自动化运维】加入读者交流群,获取更多干货内容
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值