一、configparser模块
configparser用于处理特定格式的文件(具体指配置文件,文件后缀一般为:ini,cfg,conf),其本质上是利用open来操作文件。指定格式如下:
# 注释1 ; 注释2 [section1] k1 = v1 # 值 k2 = v2 # 值 [section2] k1 = v1 # 值 [mysql] client_ip = 10.0.0.1 port = 4444 [mysqld] server_ip = 10.0.0.3 port = 3306 [liujianzuo2]
1、获取所有节点
import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) out_error_list = obj.communicate('print("hello")') print(out_error_list)
2、获取指定节点下所有的键值对
import configparser # 获取指定节点下的键值 obj = configparser.ConfigParser() # 创建编辑对象 obj.read("ini",encoding="utf-8") #读取 文件 ret = obj.items("mysql") # 键值 # [('client_ip', '10.0.0.1'), ('port', '3306')] print(ret)
3、获取指定节点下所有的键
import configparser obj = configparser.ConfigParser() # 创建编辑对象 obj.read("ini",encoding="utf-8") #读取 文件 ret = obj.options("mysql") # 选项下的key ['client_ip', 'port'] print(ret)
4、获取指定节点下指定key的值
1 obj = configparser.ConfigParser() # 创建编辑对象 2 3 obj.read("ini",encoding="utf-8") #读取 文件 4 ret = obj.get("mysql","client_ip") # 选项下的key 10.0.0.1 5 # ret = obj.getint("mysql","client_ip") # 因为默认情况下,文件的所有内容都是字符串,所以为了直接获取为int类型,那么可以改方法 6 # ret = obj.getfloat("mysql","client_ip") # 选项下的key 值为float类型 7 # ret = obj.getboolean("mysql","client_ip") # 选项下的的所有key必须都是布尔类型 8 print(ret)
5、检查、删除、添加节点
import configparser # 检查 删除 添加节点 obj = configparser.ConfigParser() # 创建编辑对象 obj.read("ini",encoding="utf-8") #读取 文件 # 检查 has_sec = obj.has_section("mysql1") # false print(has_sec) # 添加节点 obj.add_section("liujianzuo") obj.add_section("liujianzuo1") obj.add_section("liujianzuo2") obj.write(open("ini","w",encoding="utf-8")) # ['section1', 'section2', 'mysql', 'mysqld', 'liujianzuo', 'liujianzuo1', 'liujianzuo2'] obj.read("ini",encoding="utf-8") ret = obj.sections() print(ret) # 删除节点 obj.remove_section("liujianzuo") obj.remove_section("liujianzuo1") obj.write(open("ini","w",encoding="utf-8")) # ['section1', 'section2', 'mysql', 'mysqld', 'liujianzuo2'] obj.read("ini",encoding="utf-8") ret = obj.sections() print(ret)
6、检查、删除、设置指定组内的键值对
import configparser # 检查 删除 添加 指定组内的键值对 obj = configparser.ConfigParser() # 创建编辑对象 obj.read("ini",encoding="utf-8") #读取 文件 # 检查 has_opt = obj.has_option("mysql","port") print(has_opt) # 删除 obj.remove_option("mysql","port") obj.write(open("ini","w",encoding="utf-8")) ret = obj.sections() print(ret) # # 设置 obj.set("mysql","port","4444") obj.write(open("ini","w",encoding="utf-8")) ret = obj.values() print(ret)
二、shutil
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc, fdst[, length])
将文件内容拷贝到另一个文件中
import shutil shutil.copyfileobj(open('old.xml','r'), open('new.xml', 'w'))
shutil.copyfile(src, dst)
拷贝文件
shutil.copyfile('f1.log', 'f2.log')
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变
shutil.copymode('f1.log', 'f2.log')
shutil.copystat(src, dst)
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags
shutil.copystat('f1.log', 'f2.log')
shutil.copy(src, dst)
拷贝文件和权限
import shutil shutil.copy('f1.log', 'f2.log')
shutil.copy2(src, dst)
拷贝文件和状态信息
import shutil shutil.copy2('f1.log', 'f2.log')
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹
import shutil shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
import shutil shutil.rmtree('folder1')
shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。
import shutil shutil.move('folder1', 'folder3')
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对象
#将 /Users/wupeiqi/Downloads/test目录里的所有文件打包放置当前程序目录,并命名为abc.gztar import shutil ret = shutil.make_archive("abc", 'gztar', root_dir='/Users/wupeiqi/Downloads/test') #将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录 import shutil ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,
针对的zip和tar文件的处理:(强烈推荐)
对zip文件:
import zipfile # 压缩 z = zipfile.ZipFile('laxi.zip', 'w') z.write('a.log') z.write('data.data') z.close() # 解压 z = zipfile.ZipFile('laxi.zip', 'r') z.extractall() z.close()
对tar文件:
import tarfile # 压缩 tar = tarfile.open('your.tar','w') tar.add('/Users/wupeiqi/PycharmProjects/bbs2.log', arcname='bbs2.log') tar.add('/Users/wupeiqi/PycharmProjects/cmdb.log', arcname='cmdb.log') tar.close() # 解压 tar = tarfile.open('your.tar','r') tar.extractall() # 可设置解压地址 tar.close()
三、系统命令(subprocess)
在python开发[第九篇]下面的os模块下,我们曾指出过可以用来执行系统命令,程序如下:
import os os.system("dir")
但是该命令只能执行简单的shell命令,为了强大这个功能,现在python提供了一个subprocess模块。
subprocess模块的方法:
call
执行命令,返回状态码。执行命令成功,返回0,执行命令失败返回1。
######方式一#### ret = subprocess.call(["ls", "-l"], shell=False) #当shell为false时,执行的拼接命令,需要分开写在一个列表中 print(ret) #subprocess.call()就是直接执行命令,ret只是为了接收返回码的。 #####方式二##### ret = subprocess.call("ls -l", shell=True) #当shell为true时,执行的命令直接写在一个字符串中 print(ret)
check_call
执行命令,如果执行状态码是 0 ,则返回0,否则抛异常
import subprocess #######方式一######## ret=subprocess.check_call(["ls", "-l"]) #######方式二######## ret=subprocess.check_call("exit 1", shell=True) #与call()命令的区别就在于命令执行失败,会抛出异常 print(ret)
check_output
执行命令,如果执行成功,则返回执行结果,否则抛异常
import subprocess ret = subprocess.check_output("ipconfig") # 默认返回是字节类型 print(str(ret,encoding="gbk")) # windows下是gbk
上面的一系列命令也是只能执行简单的命令。并不能执行这些命令,如:在cmd执行python命令后,直接进入python解释器,然后可以再执行命令。为了解决这个问题有了,下面的方法:
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()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
第一种:
执行简单的命令:(强烈推荐)
import subprocess ret1 = subprocess.Popen(["mkdir","t1"]) ret2 = subprocess.Popen("mkdir t2", shell=True)
第二种:
输入进行某环境,然后再输入命令,如下:
import subprocess obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',) #先进入某个目录(cwd)下,再执行命令
第三种:
进入某种依赖环境,然后再执行命令,如:在cmd 环境中进入python解释器,然后再执行命令。
该种情况下,subprocess模块是定义了三条管道,三条管道(输入、输出、错误输出)均连接到了python解释器上,我们只需要:
1、向输入管道输入命令,subprocess模块会自动帮助我们把命令加载到python解释器中
2、我们在输出管道接收返回结果,若返回结果是异常,那么我们只需在错误输出管道进行接收
import subprocess #为python解释器创建管道 obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) obj.stdin.write("print(1)\n") #向输入管道输入命令 obj.stdin.write("print(2)") obj.stdin.close() cmd_out = obj.stdout.read() #在输出管道上获取返回值 obj.stdout.close() cmd_error = obj.stderr.read() #在错误管道上获取返回值 obj.stderr.close() print(cmd_out) print(cmd_error)
为了简化代码,可以如下: (强烈推荐)
import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) obj.stdin.write("print(1)\n") obj.stdin.write("print(2)") out_error_list = obj.communicate() #将输入结果不论正确或者错误,全部返回到一个列表中 print(out_error_list)
在当输入命令只有一个的时候,也可以如下:
import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) out_error_list = obj.communicate('print("hello")') print(out_error_list)
四、logging
用于便捷记录日志且线程安全的模块
1、单文件日志
import logging #filename是定义日志文件,format是定义日志格式,datefmt定义的是日期格式,level是定义日志等级 logging.basicConfig(filename='log.log', format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S %p', level=10) #建议level填写方式:level=logging.ERROR #只输出比上面定义的日志等级大的日志记录, logging.debug('debug') logging.info('info') logging.warning('warning') logging.error('error') logging.critical('critical') logging.log(10,'log')
#日志等级
CRITICAL = 50 FATAL = CRITICAL ERROR = 40 WARNING = 30 WARN = WARNING INFO = 20 DEBUG = 10 NOTSET = 0
注:只有【当前写等级】大于【日志等级】时,日志文件才被记录。
日志格式:
|
%(name)s |
Logger的名字 |
|
%(levelno)s |
数字形式的日志级别 |
|
%(levelname)s |
文本形式的日志级别 |
|
%(pathname)s |
调用日志输出函数的模块的完整路径名,可能没有 |
|
%(filename)s |
调用日志输出函数的模块的文件名 |
|
%(module)s |
调用日志输出函数的模块名 |
|
%(funcName)s |
调用日志输出函数的函数名 |
|
%(lineno)d |
调用日志输出函数的语句所在的代码行 |
|
%(created)f |
当前时间,用UNIX标准的表示时间的浮 点数表示 |
|
%(relativeCreated)d |
输出日志信息时的,自Logger创建以 来的毫秒数 |
|
%(asctime)s |
字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒 |
|
%(thread)d |
线程ID。可能没有 |
|
%(threadName)s |
线程名。可能没有 |
|
%(process)d |
进程ID。可能没有 |
|
%(message)s |
用户输出的消息 |
2、多文件日志
# 定义文件 file_1_1 = logging.FileHandler('l1_1.log', 'a', encoding='utf-8') fmt = logging.Formatter(fmt="%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s") file_1_1.setFormatter(fmt) file_1_2 = logging.FileHandler('l1_2.log', 'a', encoding='utf-8') fmt = logging.Formatter() file_1_2.setFormatter(fmt) # 定义日志 logger1 = logging.Logger('s1', level=logging.ERROR) logger1.addHandler(file_1_1) logger1.addHandler(file_1_2) # 写日志 logger1.critical('1111')
如上述创建的两个日志对象
- 当使用【logger1】写日志时,会将相应的内容写入 l1_1.log 和 l1_2.log 文件中
- 当使用【logger2】写日志时,会将相应的内容写入 l2_1.log 文件中
浙公网安备 33010602011771号