一、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)
View Code

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)
View Code

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)
View Code

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)
View Code

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)
View Code

二、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()
View Code

对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()
View Code

 三、系统命令(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)
View Code

check_call

执行命令,如果执行状态码是 0 ,则返回0,否则抛异常

import subprocess
#######方式一########
ret=subprocess.check_call(["ls", "-l"])
#######方式二########
ret=subprocess.check_call("exit 1", shell=True) #与call()命令的区别就在于命令执行失败,会抛出异常
print(ret) 
View Code

check_output

执行命令,如果执行成功,则返回执行结果,否则抛异常

import subprocess
ret = subprocess.check_output("ipconfig")  # 默认返回是字节类型
print(str(ret,encoding="gbk")) # windows下是gbk
View Code

上面的一系列命令也是只能执行简单的命令。并不能执行这些命令,如:在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')
View Code
#日志等级
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')
View Code

如上述创建的两个日志对象

  • 当使用【logger1】写日志时,会将相应的内容写入 l1_1.log 和 l1_2.log 文件中
  • 当使用【logger2】写日志时,会将相应的内容写入 l2_1.log 文件中

 

posted on 2017-06-06 18:05  进_进  阅读(97)  评论(0)    收藏  举报