4.1. 日常类库

4.1.1. 1.sys-解释器模块

用于提供对解释器相关的操作

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n)        退出程序,正常退出时exit(0)
sys.version        获取Python解释程序的版本信息
sys.maxint         最大的Int值
sys.path           返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform       返回操作系统平台名称
sys.stdin          输入相关
sys.stdout         输出相关
sys.stderror       错误相关
sys.getdefaultencoding          获取解释器默认字符编码。
sys.getfilesystemencoding       获取解释器文件系统编码。

手写进度条

import sys,time
for ii in range(101):
    sys.stdout.write('\r')  #每一次清空原行。
    sys.stdout.write("%s%%  |%s|"%(int(int(ii)/100*100),int(int(ii)/100*100) * '#'))     #一共次数除当前次数算进度
    sys.stdout.flush()      #强制刷新到屏幕
    time.sleep(0.05)

4.1.2. 2.os-操作系统模块

os模块用于提供系统级别的操作

os.getcwd()                 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname")         改变当前脚本工作目录;相当于shell下cd
os.curdir                   返回当前目录: ('.')
os.pardir                   获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2')    可生成多层递归目录
os.removedirs('dirname1')   若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname')         生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname')         删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')       列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove()                 删除一个文件
os.rename("oldname","new")  重命名文件/目录
os.stat('path/filename')    获取文件/目录信息
os.sep                      操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep                  当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep                  用于分割文件路径的字符串
os.name                     字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command")   运行shell命令,直接显示
os.environ                  获取系统环境变量
os.path.abspath(path)       返回path规范化的绝对路径
os.path.split(path)         将path分割成目录和文件名二元组返回
os.path.dirname(path)       返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path)      返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path)        如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path)         如果path是绝对路径,返回True
os.path.isfile(path)        如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path)         如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)      返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path)      返回path所指向的文件或者目录的最后修改时间

4.1.3. 3.getopt-命令行参数模块

此模块帮助脚本解析sys.argv中的命令行参数。它支持与Unix getopt()函数相同的约定(包括“-”和“-- ’)。类似于GNU软件支持的长选项也可以通过可选的第三个参数使用。

在脚本中,典型的用法是这样的:

import getopt, sys

def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(err)  # will print something like "option -a not recognized"
        usage()
        sys.exit(2)
    output = None
    verbose = False
    for o, a in opts:
        if o == "-v":
            verbose = True
        elif o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-o", "--output"):
            output = a
        else:
            assert False, "unhandled option"
    # ...

if __name__ == "__main__":
    main()

注意,通过使用`argparse <python/argparse.html#module-argparse>`__模块,可以生成更少代码和更多信息帮助和错误消息的等效命令行界面:

import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-o', '--output')
    parser.add_argument('-v', dest='verbose', action='store_true')
    args = parser.parse_args()
    # ... do something with args.output ...
    # ... do something with args.verbose ..

也可以看看

  • 模块`argparse <python/argparse.html#module-argparse>`__

    备用命令行选项和参数解析库。

4.1.4. 4.minidom-XML读写模块

内容更新

from xml.dom.minidom import parse

doc = parse('test.xml')
students = doc.getElementsByTagName('students')[0]
# 创建一个新的 student 元素节点,并追加到 students 父节点
student = doc.createElement('student')
students.appendChild(student)
# 给 student 元素节点设置属性
student.setAttribute('id', '104')
student.setAttribute('name', '许六')
student.setAttribute('age', '21')
sex = doc.createAttribute('sex') # 创建属性节点
sex.value = '女'
student.setAttributeNode(sex)
# 创建 subject1 元素节点并追加到 student 父节点
subject1 = doc.createElement('subject')
txt = doc.createTextNode('化学') # 创建文本节点
subject1.appendChild(txt)
student.appendChild(subject1)
# 创建 subject2 元素节点并插入 subject1 节点前
subject2 = doc.createElement('subject')
txt = doc.createCDATASection ('物理') # 支持转义的文本节点
subject2.appendChild(txt)
student.insertBefore(subject2, subject1)
# 保存 XML 内容
with open('test.xml', 'w', encoding='utf-8') as f:
    doc.writexml(f, addindent='', encoding='utf-8')

修改和删除 XML 节点

from xml.dom.minidom import parse
doc = parse('test.xml')
students = doc.getElementsByTagName('students')[0]
last_student = students.getElementsByTagName('student')[-1]
students.removeChild(last_student) # 删除最后一个 student 节点
first_student = students.getElementsByTagName('student')[0]
first_student.setAttribute('age', '20') # 修改元素属性值
first_subject = first_student.getElementsByTagName('subject')[0]
first_subject.firstChild.data = '体育' # 修改文本节点内容

with open('test.xml', 'w', encoding='utf-8') as f:
    doc.writexml(f, addindent='', encoding='utf-8')

4.1.5. 5.json-读写JSON模块

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它和XML一样,可用于不同系统和程序间的数据传输。与XML相比,JSON更加简单、易学、可读、高效。日常的编程中也会更多地采用JSON格式作为数据传输的首选。

在Python中可以通过标准库json来进行相关操作,其主要提供的方法如下。

  • load——加载指定文件句柄的内容进行反序列化。

  • dump——将指定的Python对象序列化后写入指定的文件句柄中。

  • loads——对指定的字符串进行反序列化。

  • dumps——将指定的Python对象序列化成JSON字符串。

##### json.loads 将字符串转换为python基本数据类型 列表字典 #####
import json
l = '["nick","jenny","car"]'
print(l,type(l))
l = json.loads(l)
print(l,type(l))

l = '{"k1":"nick","k2:":"jenny"}'
print(l,type(l))
l = json.loads(l)
print(l,type(l))

##### json.dumps 将python的数据类型列表字典转换为字符串 ######
import json
l = ["nick","jenny","car"]
print(l,type(l))
l = json.dumps(l)
print(l,type(l))

l = {"k1":"nick","k2:":"jenny"}
print(l,type(l))
l = json.dumps(l)
print(l,type(l))

##### json dump、load 文件相关 #####
import json
l = {"k1":"nick","k2:":"jenny"}
json.dump(l,open('db','w'))

ret = json.load(open('db'))
print(ret)

4.1.6. 6.openpyxl读写Excel模块

Python中可以操作Excel的模块有很多,如xlrd、xlwt、xlsxwriter、xlutils、openpyxl等。

并且这些模块都属于第三方库,也就是说在使用之前要进行安装。

其中,

  • xlrd可以读取.xls、.xlsx格式的Excel文件

  • xlwt则只能修改.xls格式的Excel文件

  • xlsxwriter则可以用于修改.xlsx格式的文件

  • xlutils是基于xlrd和xlwt之上的一个封装模块

  • openpyxl同时支持读写.xlsx、.xlsm、.xltm、.xltx文件。

通过上面的介绍可以知道,如果希望同时对.xls和、.xlsx格式的文件进行读写操作,那么至少需要安装3个库。由于各库间的API相似,因此这里仅以openpyxl模块为例进行介绍。

如果需要读写旧版本Excel文件,可以先把文件转换成新版本的.xlsx格式。

由于openpyxl不是Python的标准库,所以在使用之前需要进行安装:

$ pip install openpyxl

6.1 读取Excel文件

通过openpyxl模块操作Excel文件的大致流程如下。

(1)实例化一个Workbook对象(新建、加载已有文件)。

(2)获取指定的Worksheet对象(新建、指定已有的Worksheet对象)。

(3)基于Worksheet对象进行操作(读写)。

(4)保存或退出。

from openpyxl import load_workbook

wb = load_workbook('d:\\test.xlsx')
ws = wb.active
# 遍历全部内容
for row in ws.rows: # 遍历全部行
    for c in row: # 遍历行内全部列
        print(c.value)

# 遍历 A1 至 C4 区域的内容
for row in ws["A1:C4"]:
    for c in row:
        print(c.value)

6.2 写入 Excel 文件

>>> from openpyxl import Workbook
>>> wb = Workbook() # 创建一个新的 Workbook 对象
>>> wb.sheetnames
['Sheet']
>>> wb.active
<Worksheet "Sheet">
>>> wb.create_sheet("New_Sheet") # 新建一个 Worksheet 对象
<Worksheet "New_Sheet">
>>> wb.copy_worksheet(wb.active) # 复制一个 Worksheet 对象
<Worksheet "Sheet Copy">
>>> wb.sheetnames
['Sheet', 'New_Sheet']
>>> ws = wb['Sheet']
>>> wb.remove(ws) # 删除指定的 Worksheet
>>> wb.sheetnames
['New_Sheet']
>>> ws['A1'] = 10 # 单元格 A1 设值
>>> ws.cell(row=6, column=3, value= "Hello Python") # 单元格 C6 设值
>>> ws.append([1, 2, 3]) # 在最后一行下追加一行内容
>>> for i in range(2,6): # 对指定区域进行设值
... for j in range(1,4):
... ws.cell(row=i, column=j, value="test")
...
>>> wb.save("test.xlsx")

6.3 样式设置

>>> from openpyxl.styles import Font, colors, Alignment
>>> ws['A1'].font = ws['A1'].font = Font(name="微软雅黑", color=colors.RED, size=28,
italic=True, bold=True)) # 设置字体样式
>>> ws['B1'].alignment = Alignment(horizontal='center', vertical='center')
 # 设置对齐方式
>>> ws.row_dimensions[1].height = 30 # 设置第 1 行的高度
>>> ws.column_dimensions['A'].width = 30 # 设置 A 列的宽度
>>> # 第一种方式
>>> ws.merge_cells('A1:A3') # 合并单元格
>>> ws.unmerge_cells('A1:A3') # 拆分单元格
>>> # 第二种方式
>>> ws.merge_cells(start_row=2, start_column=1, end_row=4, end_column=5)
>>> ws.unmerge_cells(start_row=2, start_column=1, end_row=4, end_column=5)
>>> from openpyxl.drawing.image import Image
>>> img = Image('test.png')
>>> ws.add_image(img, 'A1')
>>> wb.save("test.xlsx")

上述示例中图片会被添加到Excel文件中,并且其左上角的坐标会以A1单元格的左上角坐标为锚点。需要注意的是,插入的图片如果大于指定单元格的大小,则会覆盖其他单元格的内容。

4.1.7. 7.logging-日志模块

logging 模块主要包含以下几个基础类:

  1. Logger——对外提供日志记录 API 的类。

  2. Handler——处理日志记录请求的类,并记录到指定终端上。

  3. Filter——用于过滤日志的输出内容。

  4. Formatter——指定日志输出的具体格式。

7.1 简单使用

import logging

# 获取默认的logger
logger = logging.getLogger()
# 设置日志等级, 默认为logging.WARNING
logger.setLevel(logging.ERROR)
# 进行相关类型的日志记录
logger.critical("critical")
logger.error("error")
logger.warning("warning")
logger.info("info")
logger.debug("debug")

7.2 logging配置

logging 模块支持的 4 种配置方式分别如下:

  1. 通过 logging.basicConfig函数设置。

  2. 通过 logging.config.fileConfig函数设置。

  3. 通过 logging.config.dictConfig函数设置。

  4. 通过 logging 的 API 设置。

1. logging.basicConfig函数设置

日志选项配置

import logging
logging.basicConfig(
    level=logging.INFO,
    stream=open('test.log', 'a'),
    format="%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S"
)

logger = logging.getLogger()
logger.critical("critical")
logger.error("error")
logger.warning("warning")
logger.info("info")
logger.debug("debug")

2. logging.config.fileConfig函数设置

test.conf

[loggers]
keys=root,logger01

[handlers]
keys=fileHandler,consoleHandler

[formatters]
keys=Formatter01

[logger_root]
level=DEBUG
handlers=consoleHandler

[logger_logger01]
level=DEBUG
handlers=consoleHandler,fileHandler
qualname=logger01
propagate=0

[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=Formatter01

[handler_fileHandler]
class=FileHandler
args=('logging.log', 'a')
level=ERROR
formatter=Formatter01

[formatter_Formatter01]
format=%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s
datefmt=%Y-%m-%d %H:%M:%S
import logging
from logging.config import fileConfig

fileConfig('test.conf') # 设置日志配置
root = logging.getLogger() # 获取 root Logger
logger01 = logging.getLogger("logger01") # 获取 logger01
root.debug("root debug")
root.error("root error")
logger01.debug("logger01 debug")
logger01.error("logger01 error")

3. logging.config.dictConfig函数设置

dict_conf = {
    "version": 1,
    "root": {
        "level": "DEBUG",
        "handlers": ["consoleHandler"]
    },
    "loggers": {
        "logger01": {
            "level": "DEBUG",
            "handlers": ["consoleHandler", "fileHandler"],
            "qualname": "logger01",
            "propagate": 0
        }
    },
    "handlers": {
        "consoleHandler": {
            "class": "logging.StreamHandler",
            "stream": "ext://sys.stdout",
            "level": "DEBUG",
            "formatter": "Formatter01"
        },
        "fileHandler": {
            "class": "logging.FileHandler",
            "filename": "logging.log",
            "level": "ERROR",
            "formatter": "Formatter01"
        }
    },
    "formatters": {
        "Formatter01": {
            "format": "%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s",
            "datefmt": "%Y-%m-%d %H:%M:%S"
        }
    }
}
import logging
from logging.config import dictConfig

dictConfig(dict_conf)
root = logging.getLogger()
logger01 = logging.getLogger("logger01")
root.debug("root debug")
root.error("root error")
logger01.debug("logger01 debug")
logger01.error("logger01 error")

4. logging的API设置

最后一种配置logging的方式是直接调用API来设置,这种方式相对于前面几种方式会更加灵活,可以在任意代码位置根据需要进行日志配置。具体使用示例如下:

import sys
import logging

root = logging.getLogger()
root.setLevel(logging.DEBUG)

logger01 = logging.getLogger("logger01")
logger01.setLevel(logging.DEBUG)
logger01.propagate = 0

Formatter01 = logging.Formatter("%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s")
Formatter01.datefmt = "%Y-%m-%d %H:%M:%S"

consoleHandler = logging.StreamHandler(sys.stdout)
consoleHandler.setLevel(logging.DEBUG)
consoleHandler.setFormatter(Formatter01)

fileHandler = logging.FileHandler(filename="logging.log")
fileHandler.setLevel(logging.ERROR)
fileHandler.setFormatter(Formatter01)

root.addHandler(consoleHandler)
logger01.addHandler(consoleHandler)
logger01.addHandler(fileHandler)

root.debug("root debug")
root.error("root error")

logger01.debug("logger01 debug")
logger01.error("logger01 error")

上述4种配置方式除了第一种,其他几种都支持复杂的日志配置。

除了示例中的logging.FileHandler之外,logging模块还提供了很多额外的日志处理器,具体都归档在logging.handlers模块下。

例如,RotatingFileHandler可以根据文件大小来分割日志并保留指定数量的备份文件;TimedRotatingFileHandler则可以根据时间来分割日志并保留指定数量的备份文件。

Logger 对象使用

import logging

root = logging.getLogger()

try:
    1 / 0
except Exception as e:
    root.exception(e)