模块就是一个以py结尾的python代码文件,(文件名为hello.py,则模块名为hello), 用于实现一个或多个功能(变量,函数,类等)
模块分为
1. 标准库(python自带的模块,可以直接调用
2. 开源模块(第三方模块,需要先pip安装,再调用
3. 自定义模块(自己定义的模块)
模块主要存放在/usr/local/lib/python3.6/目录下,还有其它目录下。使用sys.path查看。
[root@node1 python]# python3 Python 3.6.6 (default, Oct 10 2020, 11:59:31) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> print(sys.path) ['', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/root/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/site-packages']
# 模块路径列表,第一个值为空代码当前目录
# sys.path和linux上的$PATH很类似,如果两个目录里分别有同名模块,则按顺序来调用目录靠前的。
# sys.path的结果是一个列表,所以你可以使用sys.path.append()或sys.path.insert()增加新的模块目录。
示例: 手动在当前目录下(pycharm当前项目目录)写一个简单模块(名为hello.py)
hello.py
def funct1():
print("funct1")
def funct2():
print("funct2")
def funct3():
print("funct3")
if __name__ == "__main__":
print("haha") # 直接执行hello.py会执行这段代码
else:
print("hehe") # 通过调用模块的方式会执行这段代码
直接执行会输出haha
在同目录下写一个1.py来调用hello.py
import hello # 调用同目录下的hello模块,相当于执行了hello.py语句 hello.funct1() # 可以调用hello模块里的funct1()函数 hello.funct2() # 可以调用hello模块里的funct2()函数 hello.funct3() # 可以调用hello模块里的funct3()函数
执行输出
:与上面的hello.py同目录下,再写一个1.py来调用hello.py
:与上面的hello.py同目录下,再写一个1.py来调用hello.
hehe funct1 funct2 funct3
解析:调用模块执行hello.py因为不满足条件if __name__ == "__main__":所以执行输出hehe
其他输出为调用对应函数输出
模块导入的基本语法
导入单模块
import module1
导入多个模块
import module1,module2,module3
from导入模块所有变量函数
from hello import *
使用这种方法导入执行时无需加hello即直接执行函数即可例如
from hello import * # 调用同目录下的hello模块,相当于执行了hello.py语句 # print(__name__) funct1() # 可以调用hello模块里的funct1()函数 funct2() # 可以调用hello模块里的funct2()函数 funct3() # 可以调用hello模块里的funct3()函数
from导入模块文件中的部分函数
from hello import funct1,funct2
使用这种方法只能执行导入的函数例如执行以上则无法使用函数funct3
import语法导入与frim语法导入的区别
import导入方法相当于是直接解释模块文件
像from这样的语法导入,相当于是把hello.py里的文件直接复制过来,调用hello.py里的funct1()的话,就不需要hello.funct1()了,而是直接funct1()调用了,如果你本地代码里也有funct1(),就会冲突,后面的会overwrite前面的
# 代码一
import hello
hello.funct1() # 需要使用模块名调用
# 代码二
from hello import *
funct1() # 无需使用模块名调用
# 代码三
import hello
def funct1():
print("local funct1")
hello.funct1() # 调用模块里的函数funct1
funct1() # 调用本地的function
# 代码四
from hello import *
def funct1():
print("local funct1")
hello.funct1() # hello模块里的funct1与本地的funct1冲突
funct1() # 得到的是本地funct1的结果
为了区分本地funct1和导入的hello模块里的function,可以导入的时候做别名
#
from hello import funct1 as funct1_hello
def funct1():
print("local funct1")
funct1_hello()
funct1()
os模块
os模块.py
import os
print(os.getcwd()) # 查看当前目录
#os.chdir("/tmp") # 改变当前目录
print(os.curdir) # 打印当前目录 输出为 .
print(os.pardir) # 打印上级目录输出为 ..
#os.chdir(os.pardir) # 切换到上级目录
print(os.listdir("/")) # 列出目录里的文件,结果为相对路径并且为list类型
print(os.stat("/etc/fstab")) # 得到文件状态信息,结果为一个tuple类型
print(os.stat("/etc/fstab")[6]) # 得到状态信息(tuple)的第7个元素,也就是大小
print(os.stat("/etc/fstab")[-4])# 得到状态信息的倒数第4给元素,也就是大写
print(os.stat("/etc/fstab").st_size) # 用这个方法也可以得到文件的大小
print(os.path.getsize(__file__)) # 得到文件的大小,__file__是特殊变量,代表文件自己
print(os.path.getsize("/etc/fstab")) # 得到指定文件的大小
print(os.path.abspath(__file__)) # 得到当前程序文件的绝对路径
print(os.path.dirname("/etc/fstab")) # 得到文件绝对路径的目录名,不包括文件即/etc
print(os.path.basename("/etc/fstab")) # 得到文件名不包括目录 fstab
print(os.path.split("/etc/fstab")) # 把dirname和basename分开结果为tuple类型 ('/etc', 'fstab')
print(os.path.join("/etc","fstab")) # 把dirname和basename合并结果为字符串 fstab无需加符合/ /etc/fstab
print(os.path.isfile("/tmp/1.txt")) # 判断是否为文件 结果为bool类型 True
print(os.path.isabs("1.txt")) # 判断是否绝对路径 False
print(os.path.exists("/tmp/11.txt")) # 判断文件是否存在
print(os.path.isdir("/tmp")) # 判断是否目录
print(os.path.islink("/etc/rc.local")) # 判断是不是链接文件
# os.rename("/tmp/1.txt","/tmp/11.txt") # 文件重命名
# os.remove("/tmp/1.txt") # 删除文件
os.mkdir("/tmp/aaa") # 创建文件夹
os.rmdir("/tmp/aaa") # 删除文件夹
os.makedirs("/tmp/a/b/c/d") # 创建多层文件夹
os.removedirs("/tmp/a/b/c/d") # 删除多层文件夹
os.popen()和os.system()可以直接调用linux里的命令,二者有一点小区别:
[root@node1 模块]# cat os模块2.py
import os
# 下面这两句执行操作都可以成功,如果文件存在则覆盖创建新文件
os.popen("touch /tmp/222")
os.system("touch /tmp/333")
print(os.popen("cat /etc/fstab").read()) # 通过read()得到命令的内容,可以直接打印出内容,也可以赋值给变量
print(os.system("cat /etc/fstab")) # 除了执行命令以外,执行目录显示文件内容,还会显示返回值(0 非0 类似shell里$?判断执行是否成功)
# 所以如果是为了得到命令的结果,并且相对结果赋值进行后续操作的话就使用os.popen("pwd").read()
练习: 递归找一个目录里的所有链接文件
方法一
[root@node1 模块]# cat 查找链接文件.py
import os
dir = input("input a directory:")
def find_symlink(dir):
# 遍历输入文件夹的的目录列表
# os.listdir(dir)返回的是对应目录的一级文件或者文件夹列表
for file in os.listdir(dir):
# 使用os.path.join把文件夹即返回的列表组成文件的绝对路径
absfile = os.path.join(dir, file)
# 判断如果是链接文件则打印
if os.path.islink(absfile):
print("{} is a symlink".format(absfile))
# 如果是文件夹则循环调用函数
elif os.path.isdir(absfile):
find_symlink(absfile)
# 判断如果输入的是文件夹则调用函数
if os.path.isdir(dir):
find_symlink(dir)
# 如果不是文件夹则提示输入的不是文件夹
else:
print("what you input is not a directory")
方法二
[root@node1 模块]# cat 查找链接文件2.py
import os
dir = input("inpur a directory:")
command = "find {} -type l".format(dir)
print(command)
if os.path.isdir(dir):
#print(os.popen(command).read())
print(os.system(command))
else:
print("what you input is not a directory")
练习: 递归查找指定目录的空文件
[root@node1 模块]# cat 查找空文件.py
import os
dir = input("input a directory:")
def find_empty(dir):
for file in os.listdir(dir):
absfile = os.path.join(dir, file)
if os.path.getsize(absfile) == 0:
print("{} is a empty".format(absfile))
elif os.path.isdir(absfile):
find_empty(absfile)
if os.path.isdir(dir):
find_empty(dir)
else:
print("what you input is not a directory")
sys模块
示例
[root@node1 模块]# cat sys模块.py
import sys, os
print(sys.path) # 模块路径
print(sys.version) # python解释器版本信息
print(sys.platform) # 操作系统平台名称例如 linux
# sys.argv[0] # sys.argv[0]等同于shell里的$0,sys.argv[1]等同与shell的$1
# sys.exit()
# sys.stout.write("hellow world")
# 执行脚本命令为 python3 sys模块.py df -h
# 即本次执行sys.argv=["sys模块.py", "df", "-h"]
# 使用join方法以空格为分割符把切片后的列表["df", "-h"]组合成字符串"df -h"
command = " ".join(sys.argv[1:])
print(command)
# 打印结果为df -h
# 调用系统命令执行df -h 使用read()把执行结果打印
print(os.popen(command).read())
执行输出如下
[root@node1 模块]# python3 sys模块.py df -h ['/nas/nas/scripts/python/模块', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/root/.local/lib/python3.6/site-packages', '/usr/local/lib/python3.6/site-packages'] 3.6.6 (default, Oct 10 2020, 11:59:31) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] linux df -h 文件系统 容量 已用 可用 已用% 挂载点 devtmpfs 2.9G 0 2.9G 0% /dev tmpfs 2.9G 16K 2.9G 1% /dev/shm tmpfs 2.9G 54M 2.8G 2% /run tmpfs 2.9G 0 2.9G 0% /sys/fs/cgroup /dev/mapper/centos-root 60G 4.7G 56G 8% / /dev/sda1 197M 164M 34M 83% /boot /dev/mapper/centos-home 20G 33M 20G 1% /home /dev/mapper/centos-opt 20G 33M 20G 1% /opt tmpfs 2.9G 24K 2.9G 1% /var/lib/ceph/osd/ceph-2 tmpfs 581M 0 581M 0% /run/user/0 172.16.40.232:/nas 1.0T 215G 809G 21% /nas/nas
random模块
示例
import random
print(random.random()) # 0-1之间随机浮点数
# 0.12266246730987784
print(random.uniform(1, 3)) # 1-3之间随机浮点数
# 2.827372114420131
print(random.randint(1, 3)) # 1-3之间随机整数
# 2
print(random.randrange(1, 3)) # 1-2之间随机整数,不包括3
# 1
print(random.randrange(1, 9, 2)) # 1,3,5,7随机最后参数2为步长不包括9
# 5
print(random.choice("hello,world")) # 随机字符串里面的一个字符包括,
# d
print(random.sample("hello,world", 3)) # 随机取字符串内3个字符组成列表
# ['d', 'r', 'e']
list1 = [1, 2, 3, 4, 5]
random.shuffle(list1) # 列表随机打乱顺序
print(list1)
# [2, 4, 5, 1, 3]
输出如下
0.1634682227150962 2.130834169394176 3 1 3 h ['l', 'r', 'e'] [4, 3, 5, 2, 1]
示例:随机打印四位小写字母
import random
# 定义空字符串
code = ""
# 循环四次分别随机次数4给小写字母
for i in range(4):
# j为随机的小写字母,这个for循环只循环1次
for j in chr(random.randint(97, 122)):
# 字符串相加
code += j
# 四次循环以后输出结果即四位随机小写字母
print(code)
示例:随机打印3个字符串,字符串可以是大小写字母及数字
import random
code = ""
for i in range(4):
j = random.randint(1, 3)
if j == 1:
code += chr(random.randint(97, 122))
elif j == 2:
code += chr(random.randint(65, 91))
else:
code += str(random.randint(0, 9))
print(code)
re模块


示例
re.match示例
[root@node1 模块]# cat re.match.py
import re
print(re.match("aaa", "sdsfaaads")) # re.match匹配开通,结果为None表示匹配未成功
print(re.match("aaa", "aaasd")) # 有结果输出,表示匹配成功
# 输出为<_sre.SRE_Match object; span=(0, 3), match='aaa'>
abc=re.match("aaad+","aaa234324bbbbccc")
print(abc.group()) # 结果为aaa234324 表示匹配到的那部分字符串
re.search示例
import re
print(re.search("aaa", "sdfaaasdaaawwwsdf")) # 有结果输出,表示匹配成功;re.search就是全匹配,而不是开头(但只返回一个匹配的结果);想开头匹配的话可以使用^aaa
print(re.search("aaad+","aaa111222bbbbcccaaaa333444").group()) # 验证,确实只返回一个匹配的结果,并使用group方法将其匹配结果打印出来
re.findall示例
[root@node1 模块]# cat re.findall.py
import re
print(re.findall("aaad+", "aaa111222bbbbcccaaaa333444")) # 没有group方法,本次匹配所有aaa后面带数字,数字个数不限
# ['aaa111222', 'aaa333444']
print(re.findall("aaad+|ddd[0-9]+","aaa111222bbbbddd333444")) # 匹配aaa带任意数字 或者ddd带任意数字
# ['aaa111222', 'ddd333444']
re.sub示例
import re
print(re.sub(":", "-", "root:x:0:0:root:/root:/bin/bash"))# 全替换:成-
print(re.sub(":", "-", "root:x:0:0:root:/root:/bin/bash", count = 3))# 全替换:成-
替换练习:对输入的关键字进行屏蔽,如笨蛋使用**代替
[root@node1 模块]# cat 替换练习屏蔽关键字.py
import re
input_str = input("Please input:")
def badword_replace(input_str):
# 定义屏蔽关键字
bad_words = ["笨蛋","草","靠","羊驼"]
# 循环替换,如果遇到关键字替换 "*"*len(word)代表以输入的关键字的长度替换如果输入一个字则是一个*两个字则是两个*
for word in bad_words:
input_str = re.sub(word, "*"*len(word), input_str)
print(input_str)
badword_replace(input_str)
小结
match匹配开头 search匹配整行不一定在开头,但是只匹配第一个 match和search需要使用group方法打印匹配的字符 findall匹配所有并且把匹配到的字符以列表形式返回
re.split示例
[root@node1 模块]# cat re.split.py
import re
print(re.split(":", "root:x:0:0:root:/root:/bin/bash")) # 以:为分隔符分割后面的字符串,并转为列表
# ['root', 'x', '0', '0', 'root', '/root', '/bin/bash']
split练习:打印文件/etc/passwd以:为分隔符的最后一列
[root@node1 模块]# cat 打印文件passwd的最后一列.py
import re
f = open("/etc/passwd", "r")
for line in f:
# 把每一行以:为分隔符,分割结果为一个列表
line_list = re.split(":", line)
# 打印列表最后的元素即最后一列
print(line_list[-1], end="")
f.close()
练习:使用input输入一个字符串,判断是否为强密码: 长度至少8位,包含大写字母,小写字母,数字和下划线这四类字符则为强密码
不使用正则的方法
def check_password(password):
# 设立flag分别代表统计大小字母,小写字母,数字,下划线
# 如果出现过一次该对应字符则flag置为False即不再统计一次
flag1 = True
flag2 = True
flag3 = True
flag4 = True
# 出现不同字符的次数初始值为0
count = 0
if len(password) < 8:
print("too short")
else:
for i in password:
# 判断出现的大小字母
if i.isupper() and flag1:
count += 1
flag1 = False
continue
# 判断出现的小写字母
elif i.islower() and flag2:
count += 1
flag2 = False
continue
# 判断出现的数字
elif i.isdigit() and flag3:
count += 1
flag3 = False
continue
# 判断出现的下划线
elif i == "_" and flag4:
count += 1
flag4 = False
continue
if count >= 4:
print(count)
print("strong password")
else:
print(count)
print("weak password")
password = input("Please input password:")
check_password(password)
使用正则的方法
import re
def check_password(password):
if len(password) < 8:
print("Too short")
else:
if re.search('[A-Z]', password) and re.search('[a-z]', password) and re.search('[d]', password) and re.search('[_]', password):
print("Strong password")
else:
print("weak password")
password = input("Please input password:")
check_password(password)
解析:re.search匹配整个字符串如果有匹配则有返回,需要同时满足4个返回才输出强密码提示
练习:文件处理
1,打印/etc/passw中以daemon开头的行
2,打印包含root的行
3,打印文件中出现字符root的次数
[root@node1 模块]# cat 文件处理.py
import re
# 打开文件
f = open("/etc/passwd","r")
#print(f)
# 定义空列表用来存储以daemon开头的行
daemon_list = []
# 定义空列表用来存储包含root的行
root_list = []
# 定义空列表用来存储所有root 然后计算列表长度来计算文件中包含root的次数
root_len = []
for line in f:
# 如果开头匹配到daemon则把整行追加至列表
if re.match("daemon", line):
daemon_list.append(line)
# 如果包含root则把整行追加至列表
elif re.search("root", line):
root_list.append(line)
# 把匹配到的root分割成列表然后累加 列表root_len为一个只包含字符串root的列表
root_len += re.findall("root", line)
print("以daemon开头的行")
for i in daemon_list:
print(i,end="")
print("包含root的行")
for i in root_list:
print(i,end="")
print("包含root {}个".format(len(root_len)))
f.close()
time,datetime,calendar模块
python有三种时间类型
| 时间类型 | 描述 |
| struct_tiem | 记录时间的年月日时分等 |
| timestamp时间戳 | 记录距离1970-01-01 00:00:00有多少秒 |
| 格式化的时间字符串 | 如2020-11-05 09:00:00 |
三种类型之间的转换图

示例
import time # 加载时间模块 time.sleep(1) # 暂停1秒 print(time.localtime()) # 打印本地时间元组 # time.struct_time(tm_year=2020, tm_mon=11, tm_mday=5, tm_hour=9, tm_min=58, tm_sec=8, tm_wday=3, tm_yday=310, tm_isdst=0) print(time.gmtime()) # 打印时间元组时间为格林威治时间 # time.struct_time(tm_year=2020, tm_mon=11, tm_mday=5, tm_hour=9, tm_min=58, tm_sec=8, tm_wday=3, tm_yday=310, tm_isdst=0)
对应如下
| 序号 | 字段 | 值 |
|---|---|---|
| 0 | 4位数年 | 2008 |
| 1 | 月 | 1 到 12 |
| 2 | 日 | 1到31 |
| 3 | 小时 | 0到23 |
| 4 | 分钟 | 0到59 |
| 5 | 秒 | 0到61 (60或61 是闰秒) |
| 6 | 一周的第几日 | 0到6 (0是周一) |
| 7 | 一年的第几日 | 1到366 (儒略历) |
| 8 | 夏令时 | -1, 0, 1, -1是决定是否为夏令时的旗帜 |
print(time.strftime("%Y-%m-%d %H:%M:%S")) # 打印当前时间,格式化字符串
# 2020-11-05 10:05:38
print(time.strftime("%F %T")) # 打印当前时间,格式化字符串
# 2020-11-05 10:05:38
print(time.time()) # 打印当前时间时间戳,离1970年1月1号0点的秒数
# 1604541938.294913
示例,三种时间格式的转换
abc = time.localtime() # 把时间元组赋值给变量abc
print(time.mktime(abc)) # 把时间元组转换成时间戳,精确到秒
# 1604542173.0
print(time.strftime("%Y-%m-%d %H:%M:%S", abc)) # 时间元组转换成时间字符串,自定义格式
# 2020-11-05 10:11:20
print(time.asctime(abc)) # 时间元组转换成字符串,默认格式
# Thu Nov 5 10:13:47 2020
print(time.strptime("2020-11-05 10:30:25", "%Y-%m-%d %H:%M:%S")) # 格式化字符串转换成时间元组
# time.struct_time(tm_year=2020, tm_mon=11, tm_mday=5, tm_hour=10, tm_min=30, tm_sec=25, tm_wday=3, tm_yday=310, tm_isdst=-1)
print(time.localtime(86400)) # 打印距离1970-01-01 00:00:00时间为86400秒时间的时间元组 即24小说以后的时间元组
# time.struct_time(tm_year=1970, tm_mon=1, tm_mday=2, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=2, tm_isdst=0)
print(time.gmtime(86400)) # 打印距离1970-01-01 00:00:00时间为86400秒的时间元组,格林威治时间
print(time.ctime(335235)) # 时间戳转换成字符串时间,默认格式
# Mon Jan 5 05:07:15 1970
datetime,calendar模块
import datetime, calendar print(datetime.datetime.now()) # 打印现在时间 # 2020-11-05 11:29:17.723348 print(datetime.datetime.now()+datetime.timedelta(+3)) # 三天后时间 # 2020-11-08 11:29:17.723348 print(datetime.datetime.now()+datetime.timedelta(days=-3)) # 三天前时间 # 2020-11-02 11:29:17.723348 print(datetime.datetime.now()+datetime.timedelta(hours=5)) # 五小时后时间 # 2020-11-05 16:29:17.723348 print(datetime.datetime.now()+datetime.timedelta(minutes=-10)) # 十分钟前时间 # 2020-11-05 11:19:17.723348 print(datetime.datetime.now()+datetime.timedelta(weeks=1)) # 一星期之后时间 # 2020-11-12 11:29:17.723348 print(calendar.calendar(2020)) # 打印2020年日历 print(calendar.isleap(2020)) # 判断某年是否是闰年 # True
练习:打印出昨天的日期(格式要求为YYYY-mm-dd)
# cat 打印昨天日期.py
import time
# 方法一
# time.strftime("%Y-%m-%d",时间元组)把时间元组格式化成年月日输出
# time.localtime(时间戳)把时间戳转换成时间元组
# time.time()-86400 为现在的时间戳减去86400即24销售之前的时间戳
print(time.strftime("%Y-%m-%d", time.localtime(time.time()-86400)))
# 方法二
import datetime
abc = datetime.datetime.now() + datetime.timedelta(-1)
print(abc)
# 2020-11-05 08:52:20.352911
# str(abc)把时间转化成字符串 2020-11-05 08:52:20.352911
# 使用split方法以空格为分隔符把字符串转换成列表["2020-11-05", "08:52:20.352911"]
# 输出列表的第一个元素即格式化的日期
print(str(abc).split(" ")[0])
练习:做一个倒计时计算现在距离2021年还有多久
# cat 倒计时
import time
while True:
# 计算2021-01-01 00:00:00的时间戳
# time.strptime("2021-01-01 00:00:00", "%Y-%m-%d %H:%M:%S")使用格式化方式把时间戳转换成时间元组
# time.mktime(时间元组) 把时间元组转换成时间戳
time_stamp_2021 = time.mktime(time.strptime("2021-01-01 00:00:00", "%Y-%m-%d %H:%M:%S"))
time_stamp_now = time.time()
# print("2021年1月1日的时间戳为{}".format(int(time_stamp_2021)))
# print("现在的时间戳为{}".format(int(time_stamp_now)))
# 计算2021-01-01 00:00:00到现在的时间戳时间相差的秒数并转换成整数赋值给goal_seconds
goal_seconds = int(time_stamp_2021 - time_stamp_now)
# 如果相差为0则代表现在的时间戳已经走到2021-01-01 00:00:00了 则退出循环
if goal_seconds == 0:
break
# 否则根据相差时间的秒数计算相差的天时分秒,然后休息1秒钟继续循环
else:
print("现在距离2021年1月1日还差{}天{}时{}分{}秒".format(int(goal_seconds/86400), int(goal_seconds%86400/3600), int(goal_seconds%3600/60), int(goal_seconds%60)))
time.sleep(1)
输出如下

练习:每隔一秒循环打印2020年的日期格式为(2020-01-01)
每隔一秒打印2020年日期.py
# 方法一
import time
# 获取2020-01-01的时间元组
time_tuple_2020 = time.strptime("2020-01-01", "%Y-%m-%d")
# 获取2020-12-31的时间元组
time_tuple_2021 = time.strptime("2020-12-31", "%Y-%m-%d")
# print(time_tuple_2020)
# print(time.strftime("%Y-%m-%d", time_tuple_2020))
# 把两个时间元组转换成时间戳
time_stamp_2020 = time.mktime(time_tuple_2020)
time_stamp_2021 = time.mktime(time_tuple_2021)
# print(time_stamp_2020)
# 循环依次打印日期格式为2020-01-01
while True:
if int(time_stamp_2020) >= int(time_stamp_2021):
break
else:
# 格式化输出日期,然后把时间戳+86400即下一天的时间戳
print(time.strftime("%Y-%m-%d", time.localtime(time_stamp_2020)))
time_stamp_2020 += 86400
time.sleep(1)
每隔一秒打印2020年日期2.py
# 方法二
import time, datetime
start_time = datetime.datetime.strptime("2020-01-01", "%Y-%m-%d")
# start_time = 2020-01-01 00:00:00
delta = datetime.timedelta(days=1)
# str(start_time).split()[0]
# str(start_time)把日期转换成字符串 2020-01-01 00:00:00
# str(start_time).split()为把字符串转换成列表 ["2020-01-01", "00:00:00"] 不指定分隔符时分隔符默认为空格
while True:
if str(start_time).split()[0] == "2020-01-20":
break
else:
print(str(start_time).split()[0])
start_time = start_time + delta
time.sleep(1)
第三方模块只psutil
psutil是一个跨平台库,能够轻松实现获取系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。它主要应用于系统监控,分析和限制系统资源及进程的管理。因为是第三方模块,所以需要先使用pip命令安装后再能使用
# pip3.6 install psutil # pip3.6 list

windows下需要安装pip3.6才能执行pip安装模块,windows安装pip参考:https://www.cnblogs.com/minseo/p/13947395.html
使用PyCharm安装模块



pastil示例
import psutil
# cpu
print(psutil.cpu_times()) # cpu各时间状态,类型为tuple
# scputimes(user=26065.78125, system=24281.81250000006, idle=508792.35937499994, interrupt=168.40625, dpc=488.09375)
print(psutil.cpu_count()) # cpu核数,逻辑核数 类型为int
# 8
# memory
print(psutil.virtual_memory()) # 内存状态,类型为tuple
# svmem(total=17178800128, available=11681599488, percent=32.0, used=5497200640, free=11681599488)
print(psutil.swap_memory()) # 交换swap状态,类型为tuple
# sswap(total=19728936960, used=6905610240, free=12823326720, percent=35.0, sin=0, sout=0)
# partition
print(psutil.disk_partitions()) # 查看所有分区信息,类型为列表,列表元素类型为tuple
# [sdiskpart(device='C:\', mountpoint='C:\', fstype='NTFS', opts='rw,fixed'), sdiskpart(device='D:\', mountpoint='D:\', fstype='NTFS', opts='rw,fixed'), sdiskpart(device='E:\', mountpoint='E:\', fstype='', opts='cdrom')]
print(psutil.disk_usage("/")) # 查看分区/信息 类型为tuple
# sdiskusage(total=34340859904, used=934404096, free=33406455808, percent=2.7)
print(psutil.disk_usage("c:/")) # 查看分区c:/信息,类型为tuple
# sdiskusage(total=63260954624, used=37185134592, free=26075820032, percent=58.8)
# io
print(psutil.disk_io_counters()) # 查看所有io信息,类型为tuple
# sdiskio(read_count=376113, write_count=2186178, read_bytes=21786895872, write_bytes=46681673216, read_time=12747, write_time=17433)
print(psutil.disk_io_counters(perdisk=True)) # 查看每一个磁盘的io信息,类型为dist内部为tuple
# {'PhysicalDrive0': sdiskio(read_count=374041, write_count=2167981, read_bytes=21706172416, write_bytes=46569422848, read_time=12731, write_time=17417), 'PhysicalDrive1': sdiskio(read_count=2072, write_count=18197, read_bytes=80723456, write_bytes=112250368, read_time=16, write_time=16)}
# network
print(psutil.net_io_counters()) # 查看所有网卡的总信息(发包,收包等),类型为tuple
# snetio(bytes_sent=636645887, bytes_recv=1632356419, packets_sent=2344801, packets_recv=6043099, errin=0, errout=0, dropin=0, dropout=0)
print(psutil.net_io_counters(pernic=True)) # 查看每一个网卡的信息,类型为dict,内部为tuple
# {'Ethernet0': snetio(bytes_sent=630656366, bytes_recv=1632356483, packets_sent=2310778, packets_recv=6043100, errin=0, errout=0, dropin=0, dropout=0), 'Loopback Pseudo-Interface 1': snetio(bytes_sent=0, bytes_recv=0, packets_sent=0, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0), 'vEthernet (Default Switch)': snetio(bytes_sent=5989521, bytes_recv=0, packets_sent=34023, packets_recv=0, errin=0, errout=0, dropin=0, dropout=0)}
# process
print(psutil.pids()) # 查看所有进程id 类型为列表,元素类型为int
# [0, 4, 68, 340, 368, 392, 400, 424, 432]
print(psutil.pid_exists(1)) # 判断对应进程是否存在,元素类型为bool
# False
print(psutil.Process(0)) # 查看进程相关信息,类型为tuple
# psutil.Process(pid=0, name='System Idle Process', status='running')
# user
print(psutil.users()) # 查看当前用户登录信息,类型为list
# [suser(name='liuym', terminal=None, host='192.168.1.123', started=1604882731.7022765, pid=None)]
paramiko模块
安装
pip3 install paramiko
查看

示例:使用paramiko实现文件的上传和下载
[root@localhost 模块]# cat paramiko文件上传下载.py
import paramiko
trans = paramiko.Transport(("192.168.1.101", 22)) # 产生连接赋值给trans
trans.connect(username="root", password="password") # 连接的用户名和密码
sftp = paramiko.SFTPClient.from_transport(trans) # 指定为sftp传输模式
sftp.get("/etc/fstab", "/tmp/fstab") # 把对方机器的文件/etc/fstab 下载到本地c:/fstab (Windows目录写法,需要写全文件名,否则执行会报权限错误)
sftp.put("/etc/fstab", "/tmp/1.txt") # 把本机文件上传至远程连接主机对应目录,同理目标文件需要写全文件名,可以与原文件名不一致
trans.close()
运行没有返回,会把远程主机的文件下载以及把本地文件上传至服务器192.168.1.101
上面示例把密码写到代码中取,不安全,下面使用免密登录,需要事先设置好ssh免密
ssh-keygen ssh-copy-id -i 192.168.1.102 ssh 192.168.1.102
[root@localhost 模块]# cat paramiko文件上传下载2.py
import paramiko
trans = paramiko.Transport(("192.168.1.102", 22)) # 产生连接赋值给trans
private_key=paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")
trans.connect(username="root",pkey=private_key)# 提前使用ssh-keygen做好免密登录
sftp = paramiko.SFTPClient.from_transport(trans) # 指定为sftp传输模式
sftp.get("/etc/fstab", "/tmp/fstab2") # 把对方机器的文件/etc/fstab 下载到本地c:/fstab (Windows目录写法,需要写全文件名,否则执行会报权限错误)
sftp.put("/etc/fstab", "/tmp/1.txt") # 把本机文件上传至远程连接主机对应目录,同理目标文件需要写全文件名,可以与原文件名不一致
trans.close()
示例:使用paramiko远程登陆实现执行命令操作
[root@localhost 模块]# cat paramiko远程登陆操作.py
import paramiko
ssh = paramiko.SSHClient() # 创建一个客户端连接实例
private_key = paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy) # 加了这一句,如果第一次ssh连接要你输入yes,也不用输入了
ssh.connect(hostname="192.168.1.102",port=22,username="root",pkey=private_key)# 把password=123456换成pkey=private_key
stdin,stdout,stderr = ssh.exec_command("touch /tmp/321")
cor_res = stdout.read() # 标准输出赋值
err_res = stderr.read() # 错误输出赋值
if cor_res:
result = cor_res
else:
result = err_res
print(cor_res.decode()) # 网络传输的是二进制需要使用decode输出
print(err_res.decode())
ssh.close() # 关闭连接
执行后会在对应的主机创建文件,但是本次使用的命令是touch没有输出,如果使用其他命令例如pwd则会输出/root如果使用一个没有的命令则会输出错误输出

练习:写一个程序,针对一批次主机执行命令然后查看返回结果
[root@localhost 模块]# cat paramiko综合.py
import paramiko
def remote_exec_command(ip, command, port=22):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
private_key = paramiko.RSAKey.from_private_key_file("/root/.ssh/id_rsa")
ssh.connect(hostname=ip, port=port,username="root",pkey=private_key)
stdin, stdout, stderr = ssh.exec_command(command)
print(stdout.read().decode(), end="")
print(stderr.read().decode(), end="")
ssh.close()
# remote_exec_command("192.168.1.102","df -h")
def read_ip_port():
cmd = input("input what command you want do:")
f = open("/tmp/1.txt","r")
for line in f:
read_ip = line.strip().split(":")[0] # 去掉空格和回车然后转换成列表["192.168.1.120", "22"]
read_port = line.strip().split(":")[1]
remote_exec_command(read_ip, cmd, read_port)
f.close()
read_ip_port()
其中文本/tmp/1.txt存储了主机的用户名和端口号
[root@localhost 模块]# cat /tmp/1.txt 192.168.1.102:22 192.168.1.102:22
执行输入需要执行的命令

:与上面的hello.py同目录下,再写一个1.py来调用