python基础-7.3模块 configparser logging subprocess os.system shutil
1、 configparser模块
configparser用于处理特定格式的文件,其本质上是利用open来操作文件。
继承至2版本 ConfigParser,实现了更多智能特征,实现更有可预见性,新的应用更偏好这个版本,如果他们不需要对python老版本的兼容性,2.3版本
处理 配置文件类似如下的
1 # 注释1 2 ; 注释2 3 [section1] # 节点 4 k1 = v1 # 值 5 k2 = v2 # 值 6 7 [section2] 8 k1 = v1 # 值 9 10 [mysql] 11 client_ip = 10.0.0.1 12 port = 4444 13 14 [mysqld] 15 server_ip = 10.0.0.3 16 port = 3306 17 18 19 配置文件 ini
1、获取所有节点
1 import configparser 2 obj = configparser.ConfigParser() # 创建编辑对象 3 4 obj.read("ini",encoding="utf-8") #读取 文件 5 ret = obj.sections() # 所有选项节点,放到列表中 6 print(ret)
2、获取指定节点下所有的键值对
1 import configparser 2 3 # 获取指定节点下的键值 4 obj = configparser.ConfigParser() # 创建编辑对象 5 6 obj.read("ini",encoding="utf-8") #读取 文件 7 ret = obj.items("mysql") # 键值 # [('client_ip', '10.0.0.1'), ('port', '3306')] 8 print(ret)
3、获取指定节点下所有的建
1 import configparser 2 obj = configparser.ConfigParser() # 创建编辑对象 3 obj.read("ini",encoding="utf-8") #读取 文件 4 ret = obj.options("mysql") # 获取mysql下的。选项下的key ['client_ip', 'port'] 5 print(ret)
4、获取指定节点下指定key的值
1 #获取指定节点下的值 2 obj = configparser.ConfigParser() # 创建编辑对象 3 4 obj.read("ini",encoding="utf-8") #读取 文件 5 ret = obj.get("mysql","client_ip") # mysql节点下,client_ip key的值。选项下的key 10.0.0.1 6 # ret = obj.getint("mysql","client_ip") # 选项下的key 10.0.0.1 7 # ret = obj.getfloat("mysql","client_ip") # 选项下的key 值为float类型 8 # ret = obj.getboolean("mysql","client_ip") # 选项下的的所有key必须都是布尔类型 9 print(ret)
5、检查、删除、添加节点
1 import configparser 2 # 检查 删除 添加节点 3 obj = configparser.ConfigParser() # 创建编辑对象 4 obj.read("ini",encoding="utf-8") #读取 文件 5 6 # 检查 7 has_sec = obj.has_section("mysql1") # false 8 print(has_sec) 9 10 # 添加节点 11 obj.add_section("liujianzuo") 12 obj.add_section("liujianzuo1") 13 obj.add_section("liujianzuo2") 14 obj.write(open("ini","w",encoding="utf-8")) # ['section1', 'section2', 'mysql', 'mysqld', 'liujianzuo', 'liujianzuo1', 'liujianzuo2'] 15 obj.read("ini",encoding="utf-8") 16 ret = obj.sections() 17 print(ret) 18 # 删除节点 19 obj.remove_section("liujianzuo") 20 obj.remove_section("liujianzuo1") 21 obj.write(open("ini","w",encoding="utf-8")) # ['section1', 'section2', 'mysql', 'mysqld', 'liujianzuo2'] 22 obj.read("ini",encoding="utf-8") 23 ret = obj.sections() 24 print(ret)
6、检查、删除、设置指定组内的键值对
1 import configparser 2 # 检查 删除 添加 指定组内的键值对 3 4 obj = configparser.ConfigParser() # 创建编辑对象 5 obj.read("ini",encoding="utf-8") #读取 文件 6 7 # 检查 8 has_opt = obj.has_option("mysql","port")#检查mysql节点下有没有port 键 9 print(has_opt) 10 11 # 删除 12 obj.remove_option("mysql","port") 13 obj.write(open("ini","w",encoding="utf-8")) 14 ret = obj.sections() 15 print(ret) 16 17 # # 设置 18 obj.set("mysql","port","4444")#可以修改key值,可以直接增加键值对 19 obj.write(open("ini","w",encoding="utf-8")) 20 ret = obj.values() 21 print(ret)
2 、shutil
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中
1 import shutil 2 3 shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))#如果没有文件2,则创建一个,以a模式追加来复制的话,就是在末尾开始追加。
shutil.copyfile(src, dst)
拷贝文件
1 shutil.copyfile('f1.log', 'f2.log')
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
1 shutil.copymode('f1.log', 'f2.log')
shutil.copystat(src, dst)
拷贝状态的信息,包括:mode bits, atime, mtime, flags
1 2 shutil.copystat('f1.log', 'f2.log')
shutil.copy(src, dst)
拷贝文件和权限
1 import shutil 2 3 shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst)
拷贝文件和状态信息
1 import shutil 2 3 shutil.copy2('f1.log', 'f2.log')
以上的方法练习
1 import shutil 2 # shutil.copyfileobj(open('log.log','r'), open('a/a', 'w')) #将文件内容拷贝到另一个文件中 3 # shutil.copyfile('first.xml', 'a/a') # 拷贝文件 first.xml ===> a/a 4 # shutil.copymode('first.xml', 'a/a') # 仅拷贝权限。内容、组、用户均不变 5 # shutil.copystat('first.xml', 'a/a') # 拷贝状态的信息,包括:mode bits, atime, mtime, flags 6 # shutil.copy('log.log', 'a/a') # 拷贝文件和权限 7 # shutil.copy2('first.xml', 'a/a') # 拷贝文件和状态信息 8 9 以上方法练习
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹
1 # shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) # 将folder1下的内容 复制到folder2下面 注意 folder2 必须不存在 2 # 例子 3 # import os,sys 4 # shutil.copytree(os.path.dirname(__file__),os.path.dirname(__file__)+"/c",ignore=shutil.ignore_patterns('*.py',"*.pyc", 'l*',"*.xml"))
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
1 import shutil 2 3 shutil.rmtree('folder1') 4 5 # import os,sys 6 # shutil.rmtree(os.path.dirname(__file__)+"/c") # 删除 c目录 类似 rm -fr 不存在目录则报错
shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。
1 import shutil 2 3 shutil.move('folder1', 'folder3') 4 # shutil.move("c","b1") # 剪切c目录到b目录下 ,src即c目录不存在则报错 ,dst即b目录不存在就是重命名
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
创建压缩包并返回文件路径,例如:zip、tar
- base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
如:www =>保存至当前路径
如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/ - format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
- root_dir: 要压缩的文件夹路径(默认当前目录)
- owner: 用户,默认当前用户
- group: 组,默认当前组
- logger: 用于记录日志,通常是logging.Logger对象
1 #将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录 2 import shutil 3 ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')#一个文件夹,不是文件 4 5 6 #将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录 7 import shutil 8 ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
1 # import os,sys 2 # shutil.make_archive("my_bak","gztar",root_dir=os.path.dirname(__file__)+"/b1") 3 # shutil.make_archive(os.path.dirname(__file__)+"/a/my_bak","gztar",root_dir=os.path.dirname(__file__)+"/b1")
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细:
zipfile解压缩
1 import zipfile 2 3 # 压缩 4 # z = zipfile.ZipFile('laxi.zip', 'w')#拿到一个压缩包作为对象。如果没有这个压缩包则创建一个压缩包 5 # z.write('log.log') #添加文件到压缩包 6 # z.write('first.xml')#添加文件到压缩包 7 # z.close() 8 9 # 添加一个文件 10 # z = zipfile.ZipFile('laxi.zip', 'a') 11 # z.write('first1.xml') 12 # z.write('a/a') # 将a目和其下面的a文件一同录压缩到里面 如果存在会保存,但是仍然压缩进入 13 # z.write('b/c') # 将b目录和其下面的c文件一同压缩到里面 14 # z.write('b/b') # 将b目录和其下面的c文件一同压缩到里面 15 # z.close() 16 17 # 解压 18 # z = zipfile.ZipFile('laxi.zip', 'r') 19 # z.extractall("log.log") # 解药所有文件到log.log目录 20 # z.extract("log.log") # 解压单个文件log.log到当前目录 文件如果存在也无报错 21 # z.extract("first.xml") # 解压单个文件log.log到当前目录 文件如果存在也无报错 22 # z.close()
tarfile解压缩
1 import tarfile,os 2 # 压缩 3 # tar = tarfile.open("your.tar",'w') # 已存在不报错 4 # tar.add(os.path.dirname(__file__),arcname="nonosd") #将前面的目录重新改名为nonosd目录名 归档到your.tar中 5 # tar.add("first.xml",arcname="first.xml") #将前面的目录重新改名为nonosd目录名 归档到your.tar中 6 # tar.close() 7 8 # tar = zipfile.ZipFile('laxi.zip', 'a') 9 # tar.write('first1.xml') 10 # tar.write('a/a') # 将a目和其下面的a文件一同录压缩到里面 如果存在会保存,但是仍然压缩进入 11 # tar.write('b/c') # 将b目录和其下面的c文件一同压缩到里面 12 # tar.write('b/b') # 将b目录和其下面的c文件一同压缩到里面 13 # tar.close() 14 15 # 压缩 16 tar = tarfile.open('your.tar','r') 17 # print(tar.getmembers()) 18 print(tar.getnames()) #查看所有的文件名 19 tar.extract('first.xml') #解压单个文件 20 tar.extractall(path="a/") # 解压所有到 path 21 tar.close()
1 linux下的 压缩 和 归档 2 3 压缩工具: 4 zip: 解压缩 #可以压缩目录 不会归档链接文件 5 windows直接就指出 6 zip filename.zip srcfilename 7 8 unzip filename.zip #保留原文件 9 10 zip dir.zip dir 11 zip dir.zip dir/* 解压的话会自动创建目录 12 13 gzip:压缩 gunzip:=gzid -d 解压 #不能压缩目录 #所有先归档打包成一个文件再压缩 14 zcat:查看压缩包文件,会放到临时目录,关闭就删了 15 gzip: 16 -c :输出流改变,默认送往标准输出即屏幕,可以使用重定向将其保存为压缩文件 可以保留源 17 gzip -c file > file.gz 18 19 bzip:压缩 bunzip2:=bzip -d 解压 #不能压缩目录 #所有先归档打包成一个文件再压缩 20 bzcat : 查看压缩包文件,会放到临时目录,关闭就删了 21 格式:bz2 22 -k :保留原文件 23 24 xz:压缩 unzx:=xz -d 解压 #压缩性能更好 查看压缩包文件,会放到临时目录,关闭就删了 25 xz #不能压缩目录 #所有先归档打包成一个文件再压缩 26 27 格式 .xz 28 29 共有参数 30 -num:指定压缩比 1-9 如果不指 ,默认是6 越大压缩比越大月消耗cpu性能 31 32 33 bzip 跟gzip 不同的压缩算法,bzip比gzip压缩大文件更小,但是可能压缩小文件更大 34 35 36 归档工具: #即多个文件规程一个文件 即打包 37 tar #f必须在最后 不要随意调换次序,f 后必须是归档压缩文件名 38 tar [ options ] -f file.tar FLIE1,FILE2,FILE3..., 39 -c: 创建归档 40 -x:展开归档 41 -t :查看归档tar文件的内容如果是目录则看到文件列表 不展开而直接查看被归档的文件 42 压缩参数: 43 -z:调用用gzip 44 tar -zcf dir.tar.gz dir 45 tar -zxf dir.tar.gz 46 -j:调用bzip 47 tar -zcf dir.tar.bz2 dir 48 -J :调用 xz 49 tar -Jcf dir.tar.xz dir 50 51 归档: tar -fc dir.tar dir 52 此时合一压缩 53 xz dir.tar #比例特别高 54 unxz dir.tar.xz #解压为dir.tar 55 还原归档:-x 56 不管是什么压缩的归档文件,我们直接 tar xf 即可 57 tar xf dir.tar.{gz|bz2|xz}
3、subprocess系统命令
可以执行shell命令的相关模块和函数有:
- os.system
- os.spawn*
- os.popen* --废弃
- popen2.* --废弃
- commands.* --废弃,3.x中被移除
1 import commands 2 3 result = commands.getoutput('cmd') 4 result = commands.getstatus('cmd') 5 result = commands.getstatusoutput('cmd')
以上执行shell命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了更丰富的功能。
call
执行命令,返回状态码
1 ret = subprocess.call(["ls", "-l"], shell=False)#多个命令 2 ret = subprocess.call("ls -l", shell=True)#一个命令,放到字符串里面
check_call
执行命令,如果执行状态码是 0 ,则返回0,否则抛异常
1 import subprocess 2 ret = subprocess.check_output("ipconfig") # 默认返回是字节类型 3 print(str(ret,encoding="gbk")) # windows下是gbk
subprocess.Popen(...)
用于执行复杂的系统命令
参数:
- args:shell命令,可以是字符串或者序列类型(如:list,元组)
- bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
- stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
- preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
- close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。 - shell:同上
- cwd:用于设置子进程的当前目录 即 你执行命令的工作目录
- env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
- universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
- startupinfo与createionflags只在windows下有效
将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
执行普通命令
1 import subprocess 2 ret1 = subprocess.Popen(["mkdir","t1"]) 3 ret2 = subprocess.Popen("mkdir t2", shell=True)
终端输入的命令分为两种:
- 输入即可得到输出,如:ifconfig
- 输入进行某环境,依赖再输入,如:python
1 import subprocess 2 3 obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)
1 import subprocess 2 3 obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) 4 obj.stdin.write("print(1)\n") 5 obj.stdin.write("print(2)") 6 obj.stdin.close() 7 8 cmd_out = obj.stdout.read() 9 obj.stdout.close() 10 cmd_error = obj.stderr.read() 11 obj.stderr.close() 12 13 print(cmd_out) 14 print(cmd_error)
1 import subprocess 2 3 obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) 4 obj.stdin.write("print(1)\n") 5 obj.stdin.write("print(2)") 6 7 out_error_list = obj.communicate() 8 print(out_error_list) 9 10 交互命令 communicate 获取所有的结果
1 import subprocess 2 3 obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) 4 out_error_list = obj.communicate('print("hello")') 5 print(out_error_list)
4 、logging
用于便捷记录日志且线程安全的模块
1、单文件日志
1 import logging 2 3 4 logging.basicConfig(filename='log.log', 5 format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', 6 datefmt='%Y-%m-%d %H:%M:%S %p', 7 level=10)#level=logging.info 直接写名字最好 8 9 logging.debug('debug') 10 logging.info('info') 11 logging.warning('warning') 12 logging.error('error') 13 logging.critical('critical') 14 logging.log(10,'log')
日志等级
CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
注:只有【当前写等级】大于【日志等级】时,日志文件才被记录。
日志记录格式:
多文件写入日志的处理格式addHandler;
1 #!/usr/bin/env python 2 # _*_ coding:utf-8 _*_ 3 __author__ = 'liujianzuo' 4 5 import logging 6 #1 创建文件 7 file_1_1 = logging.FileHandler("l1_1.log","a") 8 # 创建格式 9 fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s") 10 # 文件应用格式 11 file_1_1.setFormatter(fmt) 12 13 14 file_1_2 = logging.FileHandler("l1_2.log","a") 15 fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s") 16 file_1_2.setFormatter(fmt) 17 18 19 20 logger1 = logging.Logger("s1",level=logging.ERROR) # s1 为 格式的name 21 22 logger1.addHandler(file_1_1) 23 logger1.addHandler(file_1_2)
1 # 定义文件 2 file_2_1 = logging.FileHandler('l2_1.log', 'a') 3 fmt = logging.Formatter() 4 file_2_1.setFormatter(fmt) 5 6 # 定义日志 7 logger2 = logging.Logger('s2', level=logging.INFO) 8 logger2.addHandler(file_2_1) 9 10 日志(二)