shutil
可以简单地理解为 sh + util
,shell 工具 的意思shutil
模块是对 os
模块的补充,主要针对文件的 拷贝、删除、移动、压缩和解压 操作将类似文件的对象 fsrc 的内容复制到类似文件的对象 fdst
copy 文件内容到另一个文件,可以 copy 指定大小的内容
这个方法是 shutil 模块中其它拷贝方法的基础,其它方法在本质上都是调用这个方法
让我们看一下它的源码:
def copyfileobj(fsrc, fdst, length=16*1024):
while 1:
buf = fsrc.read(length)
if not buf:
break
fdst.write(buf)
代码很简单,一看就懂。但是要注意,其中的 fsrc,fdst 都是使用 open() 方法打开后的文件对象。
copyfile()
方法对 copyfileobj()
进行了调用。将文件 src 复制到文件或目录 dst,包括权限
src 和 dst 应为字符串。如果 dst 指定目录,则文件将使用 src 的基本文件名复制到 dst 中。返回新创建的文件的路径。
# 文件复制与移动
import shutil
# 1.shutil.copyfileobj(读操作对象,写操作对象):只能复制文件的内容
fr = open("/etc/passwd", mode="r")
fw = open("/opt/mypasswd", mode="w")
shutil.copyfileobj(fr, fw)
fr.close()
fw.close()
# 2.shutil.copyfile(源文件路径,目标文件路径):只能复制文件的内容
shutil.copyfile("/etc/passwd", "/opt/passwd01")
# 3.shutil.copy(源文件路径,目标文件路径):内容权限都复制
shutil.copy("/usr/bin/ls", "/opt/ls001")
# 4.shutil.move(源文件路径,目标文件路径):移动
shutil.move("/opt/ls001", "/opt/ls002") # mv /opt/ls001 /opt/ls002
# 1.目录复制
shutil.copytree("/etc/security", "/tmp/security")
# 2.删除目录
#shutil.rmtree("/tmp/security")
案例
# 使用shutil模块的copymode()功能【只拷贝权限】
[root@localhost xxx] # ll /tmp/zj.txt # 查看/tmp/zj.txt的权限,为:644
[root@localhost xxx] # ll /usr/bin/ls # 查看/usr/bin/ls的权限,为:755
[root@localhost xxx] # python # 进入python3的解释器交互界面
>>> shutil.copymode('/usr/bin/ls', '/tmp/zj.txt') # 将文件ls的权限,拷贝给文件zj.txt, zj.txt内容不变
[root@localhost xxx] # ll /tmp/zj.txt # 查看/tmp/zj.txt的权限,为:755,权限拷贝成功
案例
# 修改文件的所有者和所属组
[root@localhost xxx] # ll /tmp/zj.txt # 查看/tmp/zj.txt的属性,属主和属组均为root
[root@localhost xxx] # python
# 使用 shutil 模块的 chown() 的方法,修改文件的属主和属组为 'adm'
>>> shutil.chown('/tmp/zj.txt', user='adm', group='adm')
[root@localhost xxx] # ll /tmp/zj.txt # 属主和属组已经被更改为 adm
# 权限管理
shutil.copymode("/usr/bin/ls","/opt/passwd01") # 只复制文件的权限
# 修改文件的所有者和所属组 useradd dc
shutil.chown("/opt/passwd01",user="dc",group="dc")
subprocess 模块主要用于执行 系统命令
subprocess 模块允许你产生新的进程,连接到它们的 输入 / 输出 / 错误 管道,并获得它们的返回状态
通俗地说就是通过这个模块,你可以在 Python 的代码里执行操作系统级别的命令,比如 “ifconfig” 、“du -sh” 等等
功能:执行 args 参数所表示的命令,等待命令结束,并返回一个 CompletedProcess 类型对象
import subprocess
# ctrl + /: 注释快捷键
# 1. subprocess.run(列表): 无法识别环境变量
subprocess.run(['ls']) # 将命令写到列表中,执行linux命令
subprocess.run(['ls', '/home']) # 将命令和操作的目录写到列表中,执行linux命令
subprocess.run('ls /home') # 以字符串形式执行linux命令,无法区分命令和目标文件,错误,会把'ls /home 当做一个整体
subprocess.run('ls /home', shell=True) # 若想以字符串形式执行,指定shell解释器
subprocess.run(['ls', '/home'])
这种方式不支持环境变量,不支持命令的扩展,不支持 shell解释器 下执行命令,所以使用字符串的方式执行 linux命令# 2. subprocess.run(字符串, shell=True)
subprocess.run('echo $HOME', shell=True) # 使用run()查看当前用户的家目录,使用shell执行命令
subprocess.run('ls /root', shell=True)
# 3. subprocess.run 返回值
subprocess.run('ls ..', shell=True) # 最后一行为返回值
day01 day02 day03 day04
CompletedProcess(args='ls ..', returncode=0)
# run方法查看上一级目录下的内容,赋值给变量result
result = subprocess.run('ls ..', shell=True)
day01 day02 day03 day04
# 查看变量result的值,为run()的返回值
result
CompletedProcess(args='ls ..', returncode=0)
# 查看result中args列表的内容,为linux命令
result.args
'ls ..'
# 查看result中returncode的值,为0\;returncode 为状态码
# 上一条命令执行成功,结果为0;反之,结果为非零值
result.returncode
'0'
需求
编写 ping 函数
用于测试远程主机的联通性
ping 通显示:x.x.x.x:up
ping 不通显示:x.x.x.x:down
# 1.通过subprocess.run执行命令
# 2.通过returncode当前指令是否执行成功,0表示成功,非0表示失败
# 3.成功->up 失败->down
import sys # 导入sys模块,用于获取位置参数
import subprocess # 导入subprocess模块,用于执行linux的ping命令
def ping(host): # 使用def定义函数ping(),用于检测主机的联通性
# subprocess.run() 在shell解释器下,执行linux命令;ping -c 2 发送两个数据包;
# %s 为占位符;&> /dev/null 将错误和正确信息都写入黑洞设备;
# result 获得run()得放回信息,returncode为状态码(0 指命令成功;非0 指失败)
result = subprocess.run('ping -c 2 %s &> /dev/null' % host, shell=True)
# 注意命令的空格: 2后要有空格,&前面要有空格
if result.returncode == 0:
return '%s:up' % host
else:
return '%s:down' % host
# 测试代码块,__name__作为python文件调用时,执行该代码块
if __name__ == '__main__':
host = sys.argv[1]
print(ping(host))
1. python支持链式多重赋值
>>> x = y = 10 # 将10赋值给x和y
>>> x # 查看x的值
10
>>> y # 查看y的值
10
>>> y = 20 # 给变量y重新赋值为20
>>> y # 查看y的值
20
>>> x # x的值不发生变化
10
2. 给列表使用多重赋值时,两个列表同时指向同一个列表空间,任何一个列表改变,另外一个随着改变
>>> alist = blist = [1, 2]
>>> alist # 查看列表alist的值
[1, 2]
>>> blist # 查看列表blist的值
[1, 2]
>>> blist[-1] = 100 # 修改列表blist中的最后一个元素为100
>>> alist # 当列表blist改变时,alist也会改变
[1, 100]
3. python 的多元赋值方法
>>> a, b = 10, 20 # 将10和20, 分别赋值给a和b
>>> a # 查看变量a的值
10
>>> b # 查看变量a的值
20
>>> c, d = 'mn' # 将m和n, 分别赋值给c和d
>>> c # 查看变量c的值
'm'
>>> d # 查看变量d的值
'n'
>>> e,f = (100, 200) # 将元组中的元素, 分别赋值给e和f
>>> e # 查看变量e的值
100
>>> f # 查看变量f的值
200
>>> m, n = ['bob', 'alice'] # 将列表中的元素,分别赋值给变量m和变量n
>>> m # 查看变量m的值
'bob'
>>> n # 查看变量n的值
'alice'
4. 在python中,完成两个变量值的互换
a, b = 100, 200 # 将100和200,分别赋值给变量a和变量b
a, b = b, a # 将变量a和变量b的值,进行交换
a # 查看变量a的值
200
b # 查看变量b的值
100
Python 标识符,字符串规则和其他大部分用 C 编写的高级语言相似
第一个字符必须是 字母或下划线 _
剩下的字符可以是字母和数字或下划线
大小写敏感
和其他的高级语言一样,python 也拥有一些被称作关键字的保留字符
任何语言的关键字应该保持相对的稳定,但是因为 python 是一门不断成长和进化的语言,其关键字偶尔会更新
关键字列表和 iskeyword() 函数都放入了 keyword 模块以便查阅
>>> import keyword # 导入模块keyword
>>> keyword.kwlist # 查看keyword模块中,包含的关键字
>>> 'pass' in keyword.kwlist # 判断 'pass' 是否是python中的关键字,是
True
>>> keyword.iskeyword('abc') # 判断 'abc' 是否是python中的关键字,否
False
builtins
模块中定义的函数,而 builtins
模块默认 在Python环境启动的时候就自动导入,所以可以直接使用这些函数需求
编写用于测试字符串的函数
函数用于确定字符串是否为合法标识符
字符串不能为关键字
import sys # 导入sys模块,用于传递位置参数
from string import ascii_letters,digits # 导入string模块的方法,获取大小写字母和数字的变量
import keyword # 导入keyword模块,用于判断是字符串是否是关键字
first_chs = ascii_letters + '_' # 变量的首字母必须是大小写字母或下划线
other_chs = first_chs + digits # 变量的其他字符必须是大小写字母,数字或下划线
def check_idt(idt): # 定义函数,判断字符是否合法,idt为形参
if keyword.iskeyword(idt): # 判断变量idt是否和关键字冲突
return '%s 是关键字' % idt # return执行时,会中断程序继续执行,返回结果
if idt[0] not in first_chs: # 判断变量idt的第一个字符是否是字母或下划线
return '第一个字符不合法' # return执行时,会中断程序继续执行,返回结果
for i in range(len(idt)): # 判断变量idt中,首字符以外的其他字符是否合法
if i == 0: # 变量idt的首字符已经判断,跳过即可
continue # 跳过本次循环
if idt[i] not in other_chs: # 判断idt首字符以外的其他字符是否合法
return '第%s个字符(%s)不合法' %(i+1, idt[i])
return '%s是合法的标识符' %idt
# 测试代码块,__name__作为python文件调用时,执行代码块
if __name__ == '__main__':
print(check_idt("test")) # 不是合法标识符
格式化字符 | 转换方式 |
---|---|
%s | 优先用str()函数进行字符串转换 |
print("字符串:%s,%s,%s" % (1, 22.22, [1, 2]))
结果
字符串:1,22.22,[1, 2]
注意
print("今天是{}的{}生日会".format("帅哥", 18))
结果
今天是帅哥的18生日会
- string.endswith(obj, beg=0, end=len(string)): 检查字符串是否以 obj 结束,如果beg 或者end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回False
- string.islower(): 如果 string 中包含至少一个区分大小写的字符,并且所有这些字符都是小写,则返回 True,否则返回False
>>> s2 = "hello world"
>>> s2.startswith('abc') #判断字符串s2,是否是以'abc'开头的,False
>>> s2.startswith('h') #判断字符串s2,是否是以'h'开头的,True
>>> s2.startswith('he') #判断字符串s2,是否是以'he'开头的,True
>>> s2.endswith('abc') #判断字符串s2,是否是以'abc'结尾的,False
>>> s2.endswith('rld') #判断字符串s2,是否是以'rld'结尾的,True
判断字符串,经常使用is..进行判断
>>> s1 = '123456' #定义一个变量s1
>>> s2 = 'hello world' #定义一个变量s2
>>> s3 = 'HELLO WORLD' #定义一个变量s3
>>> s2.islower() #判断变量s2,是否都是小写字母,True
>>> s3.isupper() #判断变量s3,是否都是大写字母,True
- string.strip(): 删除 string 字符串两端的空白
- string.upper(): 转换string 中的小写字母为大写
- string.split(str= "", num=string.count(str)): 以str为分隔符切分string,如果 num 有指定值,则仅分隔 num 个子字符串
删除 string 字符串两端的空白
>>> s4 = ' hello world '
>>> print(s4) #打印s4
>>> s4.strip() #去掉变量s4,左右两边的空白字符
>>> s4.lstrip() #去掉变量s4,左边的空白字符,右边空白字符保留
>>> s4.rstrip() #去掉变量s4,右边的空白字符,左边空白字符保留
切割字符串,拼接字符串
>>> s2 = 'hello world' #定义一个字符串变量s2
>>> s3 = 'hello.tar.gz' #定义一个变量s3
>>> s2.split() #切割字符串s2, 存入列表中,默认以空格作为分隔符进行切割
>>> s3.split('.') #切割字符串s3, 存入列表中,这里以'.'作为分隔符进行切割
>>> alist = ['tom', 'bob', 'alice'] #定义一个列表alist
>>> '_'.join(alist) #以'_'作为连接符,将列表alist中的元素拼接在一起
>>> ' '.join(alist) #以'.'作为连接符,将列表alist中的元素拼接在一起
# demo04_str.py
str01 = "hello world"
print(str01.startswith("hel")) # True
print(str01.endswith("hel")) # False
print(str01.isupper()) # False
print(str01.islower()) # True
str02 = " hello world "
print(str02.strip()) # "hello world"
print(str02.lstrip()) # "hello world "
print(str02.rstrip()) # " hello world"
str03 = "hello.tar.gz"
result = str03.split(".") # 切割,这里以'.'作为分隔符进行切割
print("split result:", result) # split result: ['hello', 'tar', 'gz']
list01 = ["world", "tar", "gz"] #
str04 = "-".join(list01)
print(str04) # world-tar-gz #拼接
需求
格式1:
import randpass2 # 将randpass2.py作为模块调用
import subprocess # 调用subprocess模块,执行linux命令
# 定义函数adduser(), 创建用户,给用户设置密码,并保存用户信息到一个文件中
def adduser(user, passwd, fname):
# 使用run()执行linux命令,检查用户是否存在,存在打印已存在,return返回none,退出
result = subprocess.run('id %s &> /dev/null' % user, shell=True)
if result.returncode == 0: #id指令执行成功,用户存在
print('%s已存在' % user)
return
else: # 用户不存在,使用run()创建用户,非交互式给用户设置密码
subprocess.run('useradd %s' % user, shell=True)
subprocess.run('echo %s | passwd --stdin %s' % (passwd, user), shell=True)
# 三引号,保留格式,用户记录用户的基本信息
info = """用户信息:
用户名:%s
密码:%s
""" % (user, passwd)
with open(fname, 'a') as fobj: # a 以追加的方式打开文件,写入用户信息
fobj.write(info)
if __name__ == '__main__':
passwd = randpass2.randpass() # 使用randpass2.py中的方法randpass(),生成一个8位的随机密码
adduser("zhangsan", passwd, '/tmp/users.txt')
格式2:
# 思路:定义函数adduser(), 创建用户,给用户设置密码,并保存用户信息到一个文件中
# 1.检查用户是否存在 id xxx,存在打印已存在; 用户不存在,使用run()创建用户,非交互式给用户设置密码
# 2.以追加的方式(mode="a")打开文件(/opt/user.txt),写入用户信息
# username:zhangsan passwd:123
import randpass2
import subprocess
def addusr():
username = input("用户:")
result = subprocess.run("id %s &> /dev/null" %username,shell=True)
if result.returncode == 0: # id指令执行成功,用户存在,不能创建
print("用户存在")
else: # id指令失败,用户不存在
subprocess.run("useradd %s" %username,shell=True)
pwd = randpass2.randpass() #调用randpass2中的randpass函数生成一个8位的随机密码
subprocess.run("echo %s | passwd --stdin %s"%(pwd,username),shell=True)
with open("/opt/user.txt",mode="a") as fw: # a 以追加的方式打开文件,写入用户信息
fw.write("username:%s passwd:%s\n"%(username,pwd))
if __name__ == '__main__':
addusr() # 调用函数