一、基础模块和正则表达式

一.运维常用模块

1.1 sys 模块

import sys
sys.argv
#接收执行当前脚本传入的参数
print(sys.argv[1:])                          --arg(参数)
#打印位置参数1至最后.0为脚本本身                   #类似shell中的$*参数(输出位置参数内容)
print(sys.version)                            #python解释器版本
print(sys.platform)                           #机器信息
print(sys.path[0])                            #获取当前脚本路径


--result
[root@client mode]# py sys.py 123 123                   --执行脚本并携带参数
['sys.py', '123', '123']
3.6.8 (default, Nov 16 2020, 16:55:22) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
linux
/root/python3/devops/mode

1.2 os模块基础

import os,sys
print(os.getenv("HOME","没有此变量返回我!"))       
#获取当前系统的环境变量 --[root@client mode]# export可以查看当前的系统环境变量
print(os.getcwd());print(sys.path[0])        
## 获取当前工作目录,即当前python脚本工作的目录路径.os和sys均可
os.mkdir("devops")
# 创建单级目录,相当于 shell 中的 mkdir dirname
os.makedirs("dir1/dir2")
# 递归创建目录
os.rmdir('./dir')
#只能删除空目录,目录中包含文件则无法删除
os.removedirs('dir1/dir2')
# 递归删除空!目录

print(os.listdir("/root/python3"))
#打印dir下的所有文件和目录,以列表的形式,无法分辨目录和文件

for root,dirs,files in os.walk("/root/python3/devops/"):
    #root,dir为目录下的子目录,files为所有子文件
    for file in files:
        new_file = os.path.join(root,file)
        #将子文件和子目录和父目录结合输出绝对路径
        print(new_file)

1.3 os.path

print(os.path.exists("os内置模块.py"))
#判断某个文件是否存在

print(os.path.isdir("devops"))
#判断后方dir是否为目录

print(os.path.isfile("D:\py-资料\devops\module_study/os内置模块.py"))
#判断是否为文件
#目录\到达文件时路径引用为/.linux中则都为/表示即可.

os.remove("D:\py-资料\devops/123.txt")
#删除某个文件

os.rename("D:\py-资料\devops/test.py","D:\py-资料\devops/haha.py")
#将某个文件改名,非绝对路径则会移动至当前路径下

dir,file = os.path.split("D:\py-资料\devops/test.py")
print(dir,file)
#将指定绝对路径的文件进行拆分,目录绝对路径和文件名.类型为元组

print(os.path.abspath("./hh.py"))
#将./规范化输出
#print(os.path.abspath("$HOME/os.py"))
#可以引入shell内置变量中的内容进行充填打印

print(os.path.join("/home","tom","bin"))
#多个路径组合返回,开头目录写/即可,结合目录带有/则从它开始

file_name = "/root/python3/devops/mode/xuexiaoqiang0304.txt"
basename = os.path.basename(file_name)
print(basename)
#去除绝对路径只要文件名

file = "D:\py-资料\devops\第二部分-业务服务监控详情\\2.4-探测Web服务质量方法\实现探测Web服务质量.py"
print(os.path.dirname(file))
#获取文件的目录部分

path = "env_test.py"
print(os.path.realpath(path))
#方法获取规范路径并解析符号链接

print(os.path.realpath(__file__))
#获取当前脚本的绝对路径

1.4 时间模块time

import time
print(time.strftime("%Y_%m_%d %H:%M:%S"))
print(time.strftime("%Y_%m_%d %X"))
print(time.strftime("%F %T"))
#以上都是输出当前时间和shell一致

time_smatp = time.time()
#定义当前时间戳
print(time.localtime(time_smatp))
#将时间戳格式化为时间输出,输出结构化时间
#结构化时间:time.struct_time(tm_year=2023, tm_mon=3, tm_mday=4, tm_hour=18, tm_min=4, tm_sec=46, tm_wday=5, tm_yday=63, tm_isdst=-1)

hh = time.localtime(time_smatp)
print(time.strftime("%Y_%m_%d %H:%M:%S",hh))
#将结构化时间格式为字符串时间


print(time.strptime('2023_03_04 18:04:46', '%Y_%m_%d %H:%M:%S'))
#将字符串时间转换为结构化时间

print(time.ctime(time.time()))
#将时间戳转化为日志ap输出
#Sat Mar  4 18:06:30 2023

print(time.asctime(time.localtime()))
#和上方效果一致,时间输出直接使用这个即可

time.sleep(10)
#当前进程休眠10s

1.5 datatime模块

import datetime
now = datetime.datetime.now()
#定义现在的时间
after = now + datetime.timedelta(3)
print(after)
#打印现在的时间加时间间隔3天,及3天后的时间
print(datetime.datetime.strftime(after,"%Y-%m-%d %T"))
#格式化间隔3天后的时间
after = now  + datetime.timedelta(3,minutes=30)
#定义时间为当前时间加3天30分钟
print(datetime.datetime.strftime(after,"%Y-%m-%d %T"))
#输出格式化后的时间

1.5.1预约倒计时

import datetime
nowtime = datetime.datetime.now()
restime = datetime.datetime.strptime("2025-03-06 12:00:00","%Y-%m-%d %H:%M:%S")
#将字符串日期格式化为结构化时间
stamp = restime - nowtime
#获取时间间隔
print(str(stamp))
day = stamp.days
h,s = divmod(stamp.seconds,3660)
#h为获取的商,s为余数,stamp的秒数除3660为分钟.商则为小时.余数为剩余秒数
#一小时有3660s
m,s = divmod(s,60)
#余数秒数除60则为分钟,商为分钟余数则为剩余秒数
print(f"{day}{h}小时{m}{s}秒!")


print("5 and 2 give:",divmod(5,2))
#divmode(5,2)结果返回5//2==2 以及5%2 == 1.返回商和余数
print("25 and 5 give:",divmod(25,5))


--交互式
import datetime
inp = input("请输入预约时间(1970-1-1 00:00:00):")
nowtime = datetime.datetime.now()
restime = datetime.datetime.strptime(inp,'%Y-%m-%d %H:%M:%S')
t = restime - nowtime
if t.days >= 0 :
    h,s = divmod(t.seconds, 3600)
    m,s =divmod(s,60)
    print(f"{t.days}{h}小时{m}{s}秒")
else:
    print("时间无法倒流!")
def handle_seconds(second):
    t = datetime.timedelta(seconds=second)

    # 计算多少小时,多少秒
    # 一个小时 3600 秒,这里divmod 内置函数取商数和余数
    h,s = divmod(t.seconds, 3600)

    # 计算多少分钟和多少秒
    m,s =divmod(s,60)

    if t.days > 0 :
        tpl = "{days}天{h}小时{m}分{s}秒"
        msg = tpl.format(days=t.days, h=h, m=m, s=s)
    elif t.days == 0 and h > 0:
        tpl = "{h}小时{m}分{s}秒"
        msg = tpl.format(h=h, m=m, s=s)
    elif h == 0 and m > 0:
        tpl = "{m}分{s}秒"
        msg = tpl.format(m=m, s=s)
    elif m == 0 and s > 0:
        tpl = "{s}秒"
        msg = tpl.format(s=s)
    else:
        msg = "刚刚"
    return msg
print(handle_seconds(60))

1.6 压缩打包模块(shutil)

1.6.1 拷贝

#shutil 是 Python3 中高级的文件 文件夹 压缩包 处理模块
import shutil

shutil.copyfile('./hh.py','../test.py')
#文件覆盖,将hh.py中的文件内容,覆盖到上一目录下的test.py文件中

1.6.2 拷贝文件和权限

import shutil

shutil.copy2("time模块.py","./hhh.py")
#完全拷贝src文件.拷贝文件和权限

shutil.copytree("./","./bak/",
                ignore=shutil.ignore_patterns("*.txt"))
#将当前目录下的所有文件,拷贝至bak目录下,不拷贝txt文件
#ignore=shutil.ignore_patterns('排除的文件名', '排除的文件夹名') 支持通配符,假如有多个用逗号隔开

1.6.3 文件夹删除

import shutil
shutil.rmtree('./bakup')
#递归删除bakup目录下的所有文件
shutil.move('./hh.py','../')
#将hh.py移动到上级目录下

1.6.4 创建压缩包

import shutil

shutil.make_archive('mode',  # 压缩后的文件名
                    'zip',  # 压缩的方式
                    '../module_study')  # 压缩的目录

shutil.make_archive('tar_mode',
                    'tar',
                    '../module_study')
ret = shutil.get_archive_formats()
#查看当前 python 环境下支持的压缩格式
print(ret)

1.6.5 解压压缩包

import shutil

shutil.unpack_archive('./mode.zip','../','zip')
#                     解压的文件名   解压到哪个路径下,压缩的格式

二.进阶模块

2.1subprocess模块学习

"""
os.system() 执行的命令只是把命令的结果输出导终端,程序中无法拿到执行命令的结果。
subprocess 是开启一个系统基本的单个进程,执行shell命令,可以得到命令的执行结果。
"""
import os
import subprocess
dir = os.getcwd()

print(subprocess.getoutput('ls -l | grep "txt"'))
#获取txt文件
result = subprocess.getstatusoutput('date')
#result为执行命令并收回命令的状态码0为正常执行
print(result)

2.2 subprocess进阶

在Python 3.5之后的版本中,官方文档中提倡通过subprocess.run()函数替代其他函数来使用subproccess模块的功能;

--案例
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)

subprocess.getstatusoutput(cmd)

subprocess.getoutput(cmd)
#参数说明:
#args: 要执行的shell命令,默认应该是一个字符串序列,如[‘df’, ‘-Th’]或(‘df’, ‘-Th’),也可以是一个字符串,如’df -Th’,但是此时需要把shell参数的值置为True。

#shell: 如果shell为True,那么指定的命令将通过shell执行。如果我们需要访问某些shell的特性,如管道、文件名通配符、环境变量扩展功能,这将是非常有用的。当然,python本身也提供了许多类似shell的特性的实现,如glob、fnmatch、os.walk()、os.path.expandvars()、os.expanduser()和shutil等。

#check: 如果check参数的值是True,且执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常,且该异常对象会包含 参数、退出状态码、以及#stdout和stderr(如果它们有被捕获的话)。

#stdout, stderr:input: 该参数是传递给Popen.communicate(),通常该参数的值必须是一个字节序列,如果universal_newlines=True,则其值应该是一个字符串。

(1.run()函数默认不会捕获命令执行结果的正常输出和错误输出,如果我们向获取这些内容需要传递subprocess.PIPE,然后可以通过返回的CompletedProcess类实例的#stdout和stderr属性或捕获相应的内容;
(2.call()和check_call()函数返回的是命令执行的状态码,而不是CompletedProcess类实例,所以对于它们而言,stdout和stderr不适合赋值为subprocess.PIPE;
(3.check_output()函数默认就会返回命令执行结果,所以不用设置stdout的值,如果我们希望在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。

#universal_newlines: 该参数影响的是输入与输出的数据格式,比如它的值默认为False,此时stdout和stderr的输出是字节序列;当该参数的值设置为True时,stdout和stderr的输出是字符串。
函数描述
subprocess.run()Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。
subprocess.call()执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。
subprocess.check_call()Python 2.5中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(…, check=True)。
subprocess.check_output()Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。
subprocess.getoutput(cmd)接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。
subprocess.getstatusoutput(cmd)执行cmd命令,返回一个元组(命令执行状态, 命令执行结果输出),其功能类似于commands.getstatusoutput()。

三.正则

3.1 基础正则

import re
str = "devops_study 2023"
result = re.search('.',str)
#匹配除换行符(\n)以外的单个任意字符.匹配一个则停止
print(result)
--<re.Match object; span=(0, 1), match='d'>
#span为所在的索引位,match为匹配内容

result = re.search("^devops",str)
#匹配devops开头的内容

result = re.findall(pattern="^devops",string=stre)
#匹配devops开头的内容,findall根据pattern的方式匹配字符串内容返回列表元素的结果,可以通过for循环取出


result = re.search("2023$",stre)
#匹配2023结尾的内容

result = re.search("[_2]",stre)
#匹配[]中的任意内容如果内容中存在_则停止匹配,返回当前匹配结果

result = re.search("[A-Z,0-9]",stre)
#匹配[]中的任意内容如果内容中,A-Z命中后停止匹配

stre = "$00123"
result = re.search("[00$]",stre)
#匹配[]中的任意内容如果内容,$为无效字符,哪个字符先匹配则停止
span=(0, 1), match='$'

stre = 'ab58abc'
result = re.search('[^ab]',stre)
#^在中括号中是取反的意思,比如[^ab]匹配到不是 a、b中的任意一个其他字符.

3.2 特殊正则

result = re.search('5\w\w',stre)
#匹配字符中包含5后面是俩个任意字符的内容
----span=(2, 5), match='58a'

stri = "嫦娥¥号"
result = re.search('嫦娥\W号',stri)
a = result.group()
#group将结果进行截取,默认group0,返回整体
print(a)
----嫦娥¥号

stri = '联想 lenovo 2020\\'
result = re.search('\\\\',stri)
#匹配俩个斜杠
#因为正则表达式里匹配一个反斜杠必须是 '\\' ,而每个反斜杠在普通的 Python 字符串里都要写成 '\\' 。


stri = '联想 lenovo 2020\\'
result = re.search('[en]',stri)
#查找e或n的某个字符,查到一个则停止


stri = 'hello2020 hello'
result = re.search(r'\bhello\b',stri)
#匹配单词边界,匹配hello前后各一个字符或不存在字符.后方多字符则不匹配.


result = re.search('(eno)',stri)
#匹配eno组合的字符

3.3 拓展正则

.:匹配除换行符(\n)以外的单个任意字符 
^:匹配整个字符串的开头 
$:匹配整个字符串的结尾 
[]:匹配中括号内字符中的任何一个 比如:[1a] 匹配到 1 或者 a  
[-]:匹配连续的字符范围 比如 [0-9] 表示 09之间的任意一个数字  
\w:匹配单个字母、数字、汉字或下划线
\d:匹配单个数字
\s:匹配单个任意的空白符
\b:匹配单词的开始或结束
    
*:对它前面的正则模式匹配0到任意次重复, 尽量多的匹配字符串。 | ab* 会匹配 'a''ab', 或者 'a'后面跟随任意个 'b'。a只能出现一次 
+:对它前面的正则式匹配1到任意次重复。 | lv6+ 匹配 lv 后面跟随1个以上到任意个 '6',它不会匹配 'lv'。
?:对它前面的一个正则模式匹配01次重复。 | lv6? 匹配 lv 和 lv6,要么没有6要么出现1{m}:重复它前一个正则模式 m 次 a{2} 匹配 aa 
{m,}:重复它前一个正则模式 m 次或 m 次以上 a{2,} 匹配 aa 或连续两个 a以上 
{m, n}:重复前一个正则模式 m 到 n 次之间的任意一个都可以 a{2,5} 匹配连续2 个到 5 个之间的 a。如:'aa', 'aaa', 'aaaa', 'aaaaa'

3.4 python使用正则

3.4.1 常用方法
import re
"match"
#只在整个字符串的起始位置进行匹配
string = "isinstance yangge enumerate www.qfedu.com 1997"
r = re.match('is\w+',string)
#匹配is后面是任意字符出现1次到多次
print(r)

"search"
#从整个字符串的开头找到最后,当第一个匹配成功后,就不再继续匹配。
r = re.search('a\w+',string)
#查询字符串开头为a,后方为任意字符出现1-n次
print(r)

"findall"
#搜索整个字符串,找到所有匹配成功的字符串,比把这些字符串放在一个列表中返回。
r = re.findall('a\w+',string)
#查询字符串中所有组合为a+任意字符重复1-n的内容
print(r)

"sub"
#把匹配成功的字符串,进行替换。
r = re.sub('a\w+',"哈哈哈",string,1)
#查询a后方任意字符出现1-n次,替换为哈哈哈,针对str文本,替换1次
print(r)

"split"
#以匹配到的字符进行分割,返回分割后的列表
r = re.split('a',string,1)
#遇到a进行分割,分割一次
print(r)

"""使用多个界定符分割字符串"""
line = 'asdf fjdk; afed, fjek,asdf,  foo'
r = re.split(r'[;,\s]\s*',line)
#r不专业字''号中的内容,遇到;、,、空格,空格后面是任意字符内容,进行分割
print(r) #['asdf', 'fjdk', 'afed', 'fjek', 'asdf', 'foo']
3.4.2 分组
3.4.2.1 match
import re
"""==从已经成功匹配的内容中,再去把想要的取出来=="""
"match"
stre = 'isinstance yangge enumerate www.qfedu.com  1997'
r = re.match("is(\w+)",stre)
#此时匹配的是isinstance的长字符串,分组为instance内容
r = r.groups()
#打印分组中的内容
print(r)
#('instance',)
"""
group()返回类型为 字符串,表示返回整个匹配对象作为一个字符串

group(1)返回类型为 字符串,表示返回正则表达式的第1个( )匹配的对象,group(0)等同于group()返回整个匹配对象

groups()返回类型为元祖,表示返回正则表达式每个子组(每个())匹配的对象依次放进元祖里,如果正则表达式没有(),则返回空元祖()。
"""
3.4.2.2 search
import re
"search"
string = 'isinstance yangge enumerate www.qfedu.com  1997'
r = re.search("is\w+\s(?P<name>y\w+e)", string)
#匹配is打头后面为字母或特殊字符+空白符,命名分组,内容为y+任意字符出现1-n次+e结尾,分组名为name
print(r.group())
#返回整个匹配对象
print(r.groups())
#返回分组内容匹配的对象
print(r.groupdict())
#打印分组的信息为字典类型:{'name': 'yangge'}

3.4.2.3 findall && finditer
import re
"findall"
string = 'isinstance yangge enumerate www.qfedu.com  1997'
r = re.findall("a(?P<name>\w+)", string)
#findall,查找字符串中所有满足条件的字符,返回list
#匹配a打头,分组名称为name,正则内容为任意字符出现1-n次
print(r)
#输出为字符按包含a,中的后面字符出现1-n次的内容
r = re.findall("a(\w+)",string)
print(r)
#findall之返回分组内的内容,不返回前方的字符匹配内容

haystack = "sadbutsad"
needle = "sad"
import re
f = re.finditer(needle,haystack)    #finditer返回非重叠字符的mathch对象。多次匹配
for i in f:
    print(i)            #返回math对象
    print(i.span())    #返回下标
3.4.2.4 split
import re
"findall"
string = 'isinstance yangge enumerate www.qfedu.com  1997'
r = re.split("(an)",string)
#字符串中匹配到an就进行分割
print(r)
tag = 'value="1997/07/01"'
s = re.sub(r'(value="\d{4})/(\d{2})/(\d{2})"', r'\1年\2月\3日"', tag)
#sub:匹配正则内容进行替换,数字出现4次,2次,2次,替换为分组1+年,分组2+年,分组3+年.对tagstr进行操作
print(s)

3.5 常用正则

"常用正则"
"邮箱"
import re
context = "shark123@qq.com,shark123@163.com"
pattern = re.compile(r"[a-zA-Z0-9_-]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}")
#re.compile可以提前编译正则表达式(定义正则匹配规则).内容为:a-9加特殊字符集合开头,@a-9+.a-Z出现2-3次,因为正常邮箱结尾都为2-3次cn、com
result = pattern.findall(context)
#re.findall可以搜索多种匹配模式(全文匹配)
print(result)

"手机号"
conetxt = """
白日依19989881888山尽,黄河入45645546468798978海流。
欲穷12345千里目,更上15619292345一层楼。
"""
import  re
pattern = r"(1\d)\d{7}(\d{2})"
#pattern方法为给开头1\d进行分组(俩位数),即开头的俩个数字(1\d).中间位数为7位,(\d{2})即尾数为2个数字作为第二个分组
print(re.sub(pattern,r"\1*****\2",conetxt))
#\1引用正则中的第一个分组,也就是1开头,结尾为分组内容2
new_pattern = r"1\d{10}"
#提取电话号码为1开头任意数字出现10次
result = re.findall(new_pattern,conetxt)
for i in result:
    print(f"提取到的电话号码为:{i}")

"IP地址"
s = 'lenovo 192.137.1.336 shark 192.168.1.130 255.255.255.255 qf 192.168.1.138 lenovo,34.106.23.123,8.8.8.8'
pattern = r'(?<![.\d])(?:2[0-3]\d|1\d\d|[1-9]\d{0,1})\.(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d{0,1})\.){2}?(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d{0,1})(?![.\d])'
result = re.findall(pattern,s)
print(result)

"贪婪和非贪婪"
print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']
# 匹配所有包含小数在内的数字。
# 查询数字出现1-n次,.出现0-1次数字出现1-n次

print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']
##.*默认为贪婪匹配,匹配a后面除换行符的任意单个字符.b为尾部


print(re.findall('a.*?b','a1b22222222b')) #['a1b']
#.*?为非贪婪匹配:推荐使用
#a后方单个任意字符,出现0或1次,则中间的字符只能出现1次

print(re.findall('a.*?b','ab,asd,asdab,asb')) #['ab', 'asd,asdab', 'asb']
#a.*?b:a打头换行符除外任意单个字符,出现0-1次.只能匹配到a-b或者ab

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

运维神经科主任

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值