shutil 模块
基本概念
shutil
可以简单地理解为 sh + util
,shell 工具 的意思
shutil
模块是对 os
模块的补充,主要针对文件的 拷贝、删除、移动、压缩和解压 操作
shutil 模块的主要方法
复制和移动
shutil.copyfileobj(fsrc, fdst)
- 将文件的对象 fsrc 的内容复制到文件的对象 fdst
案例
1 2 3 4 5 6 7 8
| import shutil
fr = open("/etc/hosts", mode="r") fw = open("/opt/myhosts", mode="w") shutil.copyfileobj(fr, fw) fr.close() fw.close()
|
shutil.copyfile(src, dst)
- 将名为 src 的文件的内容复制到名为 dst 的文件
案例
1 2 3
| import shutil
shutil.copyfile("/usr/bin/ls", "/opt/myls")
|
shutil.copy(src, dst)
将文件 src 复制到文件或目录 dst,包括权限
案例
1 2 3
| import shutil
shutil.copy("/usr/bin/ls", "/opt/myls2")
|
shutil.move(src, dst)
- 递归地将文件或目录(src)移动到另一个位置(dst),并返回目标
案例
1 2
| import shutil shutil.move("/opt/myls2", "/opt/myls3")
|
目录操作
shutil.copytree(src, dst)
- 递归地复制以 src 为根的整个目录树,返回目标目录。由 dst 命名的目标目录不能已经存在
案例
1 2
| import shutil shutil.copytree('/etc/security', '/opt/security')
|
shutil.rmtree(path)
- 删除整个目录树; *路径 *必须指向目录, 空目录或者非空目录都可使用
1 2
| import shutil shutil.rmtree("/opt/security")
|
权限管理
shutil.copymode(src, dst)
- 将权限位从 src 复制到 dst
- 文件内容,所有者和组不受影响
- src 和 dst 是以字符串形式给出的路径名称
案例
1 2 3
| import shutil
shutil.copymode("/usr/bin/ls", "/opt/myhosts")
|
shutil.chown(path, user=None, group=None)
案例
1 2
| import shutil shutil.chown("/opt/myhosts",user="cuihua",group="cuihua")
|
os 模块
- 对文件系统的访问大多通过 python 的 os 模块实现
- 该模块是 python 访问操作系统功能的主要接口
- 有些方法,如:copy 等,并没有提供,可以使用 shutil 模块作为补充
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| >>> import os >>> os. >>> os.getcwd() >>> os.listdir() >>> os.listdir('/tmp') >>> os.mkdir('/tmp/mytest') >>> os.mkdir('/tmp/demo/abc') >>> os.makedirs('/tmp/demo/abc') >>> os.chdir('/tmp/demo') >>> os.getcwd() >>> os.listdir() >>> os.symlink('/etc/passwd', 'mima') >>> os.remove('abc') >>> os.rmdir('abc') >>> os.rmdir('/var/tmp') >>> os.unlink('mima')
>>> os.path. >>> os.mkdir('abc') >>> os.path.abspath('abc') >>> os.path.basename('/tmp/demo/abc') >>> os.path.basename('/tmp/demo/abc/') >>> os.path.dirname('/tmp/demo/abc') >>> os.path.split('/tmp/demo/abc') >>> os.path.join('/tmp/demo', 'abc') >>> os.path.is >>> os.path.isabs('tmp/abc/xyz') >>> os.path.isabs('/tmp/abc/xyz') >>> os.path.isdir('/tmp/demo/abc') >>> os.path.isdir('/tmp/demo/xyz') >>> os.path.isfile('/etc/hosts') >>> os.path.isfile('/etc/') >>> os.path.islink('/etc/grub2.cfg') >>> os.path.exists('/etc/hostname')
|
subprocess 模块
基础概念
- subprocess 模块主要用于执行 系统命令
- subprocess 模块允许你产生新的进程,并获得它们的返回状态
- 通俗地说就是通过这个模块,你可以在 Python 的代码里执行操作系统级别的命令,比如 “ifconfig” 、”du -sh” 等等
run 方法
功能:执行 args 参数所表示的命令,等待命令结束,并返回一个 CompletedProcess 类型对象
1 2 3 4 5
| >>> import subprocess >>> subprocess.run(['ls']) >>> subprocess.run(['ls', '/home']) >>> subprocess.run('ls /home') >>> subprocess.run('ls /home', shell=True)
|
通过 shell 执行命令
subprocess.run(['ls', '/home'])
这种方式不支持环境变量,不支持命令的扩展,不支持 shell解释器 下执行命令,所以使用字符串的方式执行 linux命令
1 2
| >>> subprocess.run('echo $HOME', shell=True) >>> subprocess.run('ls /root', shell=True)
|
run 方法返回值
- run 方法查看上一级目录下的内容,使用 shell 执行命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| >>> 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'
|
注意
- subprocess 模块虽然可以支持所有的 linux 命令,但不可乱用,放弃其他的模块
- subprocess 模块编写的代码,不具有跨平台性,不能在 windows,mac 等系统使用
练习 1:调用 ping 命令
需求
- 调用 ping 命令
- 编写 ping 函数
- 用于测试远程主机的联通性
- ping 通显示:x.x.x.x:up
- ping 不通显示:x.x.x.x:down
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import subprocess def ping(host):
result = subprocess.run('ping -c 2 %s &> /dev/null' % host, shell=True) if result.returncode == 0: return '%s:up' % host else: return '%s:down' % host
if __name__ == '__main__': print(ping("127.0.0.1"))
|
异常
什么是异常
程序在运行时,如果 Python 解释器
遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常
异常是因为程序出现了错误,而在正常控制流以外采取的行为
- 这个行为又分为两个阶段:
- 首先是引起异常发生的错误
- 然后是检测(和采取可能的措施)阶段
Python 中的异常
当程序运行时,因遇到未解的错误而导致中止运行,便会出现 traceback 消息,打印异常
1 2
| KeyboardInterrupt EOFError
|
python 中异常演示
1 2 3 4 5 6
| >>> a + 5 >>> 'hello'[5] >>> a = 10 >>> if a = 10: >>> n = input('number:' ) >>> n = input('number: ')
|
错误类型捕获
- 在程序执行时,可能会遇到 不同类型的异常,并且需要 针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
- 语法如下:
1 2 3 4 5 6 7 8 9 10 11
| try: pass except 错误类型1: pass except (错误类型2, 错误类型3): pass except Exception as result: print("未知错误 %s" % result)
|
try-except 语句
- 定义了进行异常监控的一段代码,并且提供了处理异常的机制
1 2 3 4 5
| try: n = int(input('number: ')) print(n) except ValueError: print('无效的输入')
|
带有多个 excepct 的 try 语句
- 可以把多个 except 语句连接在一起,处理一个try 块中可能发生的多种异常
1 2 3 4 5 6 7 8 9 10
| try: n = int(input('number: ')) print(n) except ValueError: print('无效的输入') except KeyboardInterrupt: print('\nBye-bye') except EOFError: print('\nBye-bye')
|
1 2 3 4 5 6 7
| [root@localhost xxx] number: 无效的输入 [root@localhost xxx] number: ^CBye-bye [root@localhost xxx] number: Bye-bye
|
捕获未知错误
- 在开发时,要预判到所有可能出现的错误,还是有一定难度的
- 如果希望程序 无论出现任何错误,都不会因为
Python
解释器 抛出异常而被终止,可以再增加一个 except
语法如下:
1 2
| except Exception as result: print("未知错误 %s" % result)
|
异常参数 e
- 异常也可以有参数,异常引发后它会被传递给异常处理器
- 当异常被引发后参数是作为附加帮助信息传递给异常处理器的
查看异常提示信息
1 2 3 4 5
| >>> n = int(input('number: ')) number: Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: invalid literal for int() with base 10: ''
|
使用多个except的try语句,实现异常参数
1 2 3 4 5 6 7 8 9 10 11 12 13
| try: n = int(input('number: ')) print(n) except ValueError as e: print('无效的输入', e) except KeyboardInterrupt: print('\nBye-bye') except EOFError: print('\nBye-bye')
[root@localhost day01] number: 无效的输入 invalid literal for int() with base 10: ''
|
使用多个except的try语句,捕获多个异常
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| try: n = int(input('number: ')) print(n) except ValueError as e: print('无效的输入', e) except (KeyboardInterrupt, EOFError): print('\nBye-bye')
[root@localhost day01] number: ^C Bye-bye [root@localhost day01] number: Bye-bye
|
else 子句
- 在 try 范围中没有异常被检测到时,执行 else 子句
- 在else 范围中的任何代码运行前,try 中的所有代码必须完全成功
1 2 3 4 5 6 7 8 9 10 11 12 13
| try: n = int(input('number: ')) except ValueError as e: print('无效的输入', e) except (KeyboardInterrupt, EOFError): print('\nBye-bye') else: print(n)
[root@localhost day01] number: 19 19
|
finally子句
- finally 子句是 无论异常是否发生,是否捕捉都会执行的一段代码
- 如果打开文件后,因为发生异常导致文件没有关闭,可能会发生数据损坏,使用finally 可以保证文件总是能正常的关闭
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| try: n = int(input('number: ')) except ValueError as e: print('无效的输入', e) except (KeyboardInterrupt, EOFError): print('\nBye-bye') exit() else: print(n) finally: print('Done')
[root@localhost day01] number: Bye-bye Done
[root@localhost day01] number: 19 19 Done
|
自定义异常
抛出异常—raise
应用场景
- 在开发中,除了 代码执行出错
Python
解释器会 抛出 异常之外
- 还可以根据 应用程序 特有的业务需求 主动抛出异常
示例
- 提示用户 输入密码,如果 长度少于 8,抛出 异常
![image-20210901174254244]()
注意
- 当前函数 只负责 提示用户输入密码,如果 密码长度不正确,需要其他的函数进行额外处理
- 因此可以 抛出异常,由其他需要处理的函数 捕获异常
抛出异常
Python
中提供了一个 Exception
异常类
- 在开发时,如果满足 特定业务需求时,希望 抛出异常,可以:
- 创建 一个
Exception
的 对象
- 使用
raise
关键字 抛出 异常对象
需求
- 定义
input_password
函数,提示用户输入密码
- 如果用户输入长度 < 8,抛出异常
- 如果用户输入长度 >= 8,返回输入的密码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| def input_password(): pwd = input("请输入密码:") if len(pwd) >= 8: return pwd ex = Exception("密码长度不够")
raise ex if __name__ == '__main__': user_pwd = input_password() print(user_pwd)
|
练习 4:自定义异常
需求
- 编写一个函数,接收姓名和年龄,如果年龄不在1到120之间,产生 ValueError 异常
1 2 3 4 5 6 7 8
| def get_info(name, age): if not 0 < age < 120: raise ValueError('无效的年龄(1 ~ 119)') else: print('%s is %s years old' %(name, age))
|