Python3常用标准库
趁着有时间,把一些我用过的常用标准库进行整理和复习。
time
用法 | 说明 |
---|---|
time.time() |
返回时间戳(从1970年1月1日00:00:00开始计算) |
time.localtime() |
返回当前时间的结构化时间(struct_time)对象,可以用.tm_year 等获取年等数据 |
time.gmtime() |
返回世界标准时间的结构化时间(struct_time)对象 |
time.mktime(struct_time) |
结构化时间转化为时间戳 |
time.strftime("时间格式", struct_time) |
结构化时间转化为字符串时间 |
time.strptime("字符串时间", "时间格式") |
字符串时间转化为结构化时间 |
time.asctime([tuple]) |
时间元组转换为字符串。如果时间元组不存在,则使用localtime()返回的当前时间 |
time.ctime(seconds) |
将时间秒数转换为时间字符串,相当于time.asctime(localtime(seconds)) 。second不存在,则使用localtime()返回的当前时间。 |
常用时间占位符
- 年 %Y
- 月 %m
- 日 %d
- 时 %H (24小时制)
- 分 %M
- 秒 %S
- 时分秒 %X ,相当于
%H:%M:%S
datetime
虽然python库中已经有了time库,但time库不支持对时间的加减等操作,因此就有了datetime库。
用法 | 说明 |
---|---|
datetime.datetime.now() |
获取当前时间,返回datetime.datetime 对象,有year, month, day, hour, minute, second, microsecond等属性。 |
datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0 |
这是一个类,表示两个 date 或者 time 的时间间隔。 |
datetime.datetime.fromtimestamp(seconds) |
将秒数转换为datetime.datetime 对象,datetime.datetime.fromtimestamp(time.time()) <==>datetime.datetime.now() |
datetime.timetuple() |
这是datetime.datetime对象的方法,返回结构化时间,time.localtime() 的返回类型相同 |
datetime.replace(year=self.year, month=.., day=.., hour=.., minute=.., second=.., ...) |
一样是datetime.datetime对象的方法,可以替换当前对象的year等属性,详见文档 |
有了以上几个方法,我们就可以对时间进行加减操作,并可以在time和datetime之间进行转换。
- datetime.datetime之间可以相减,结果为datetime.timedelta对象,有days和seconds属性
- datetime.datetime与datetime.timedelta之间可以加减,结果为datetime.datetime对象
- datetime.timedelta本身可以乘以一个数,以表示不同的时间间隔
import time
import datetime
def main():
date1_string = "2017/6/8 15:0:0"
# date1_string转换为时间戳
# strptime -> mktime -> fromtimestamp ==> datetime.datetime
date1 = datetime.datetime.fromtimestamp(time.mktime(
time.strptime(date1_string, '%Y/%m/%d %H:%M:%S')))
date2 = datetime.datetime.now() # 获取当前时间
# 使用datetime.datetime对象之间 进行操作,结果为datetime.timedelta对象
result1 = date2 - date1 # 两个时间过了多久了
print(result1.days, result1.seconds)
# datetime.datetime与datetime.timedelta之间的操作, 结果是datetime.datetime对象
year = datetime.timedelta(days=365) # 一年时间
result2 = date2 + 2 * year # 当前时间的两年后
print(result2.year, result2.month, result2.day)
if __name__ == '__main__':
main()
random
使用random可以生成伪随机数。
用法 | 说明 |
---|---|
random.seek(time.time()) |
初始化随机数生成器 |
random.random() |
生成[0.0, 1.0) 范围内的一个随机浮点数 |
random.uniform(num1, num2) |
返回[num1, num2] [1] 中一个随机浮点数 |
random.randint(num1, num2) |
生成[num1, num2] 范围内的一个整数,num1, num2均为int |
random.randrange(num1, num2) |
生成[num1, num2) 范围内的一个整数,num1, num2均为int |
random.choice(iterable_obj) |
从可迭代对象中随机取一个元素 |
random.sample(iterable_obj, n) |
从可迭代对象中随机取n个元素组成一个列表返回 |
random.shuffle(x) |
将序列 x 随机打乱位置。不可变的可以用random.sample(x, k=len(x)) |
生成验证码例子:
import random
def make_code(n):
res = ''
for i in range(n):
letter = chr(random.randint(65, 90)) # 生成A-Z的任意一个字母
number = str(random.randint(0, 9)) # 生成0-9的任意一个数
res += random.choice([letter, number])
return res
print(make_code(9))
sys
sys模块提供了一些与解释器相关的变量和函数。
用法 | 说明 |
---|---|
sys.argv |
返回一个列表,第一个元素是程序本身路径,其他元素是命令行输入参数 |
sys.exit(n) |
退出程序,实现方式是抛出一个SystemExit 异常。正常时n为0,非零值视为“异常终止”。大多数系统要求该值的范围是 0~127。 |
sys.path |
返回模块的搜索路径,其本质上是列表,可以使用append方法添加路径,导入特定模块。 |
sys.platform |
返回平台名称(Linux:'linux',Windows:'win32',Mac OS X:darwin') |
sys.stdout.write(" ") |
不换行打印 |
sys.stdout.flush() |
刷新 |
os
一般用于对文件和目录进性操作的模块。
路径相关
os.getcwd()
获取当前工作目录
os.chdir(path)
改变当前工作目录
文件/目录操作
用法 | 说明 |
---|---|
os.mkdir(path) |
创建目录 |
os.makedirs(path) |
递归创建目录 |
os.redir(path) |
删除空目录 |
os.removedirs(path) |
递归删除空目录 |
os.remove(path) |
删除文件 |
os.rename(old_name, new_name) |
更改文件或目录名 |
os.stat(path) |
查看文件详情( 'st_atime', 'st_ctime', 'st_mtime', 'st_size'等) |
输出符号
用法 | 说明 |
---|---|
os.sep |
输出系统分隔符(如:\ 或/ ) |
os.linesep |
输出行终止符(win:\r\n ,linux:\n ) |
os.pathsep |
输出路径分割符(win:; ,linux:: ) |
path
path是os库中的一个模块,里面有很多实用的函数。
用法 | 说明 |
---|---|
os.path.split(path) |
把路径分割为(目录, 文件名) |
os.path.abspath(path) |
返回path规范化的绝对路径 |
os.path.normpath(path) |
返回path规范化后的结果 |
os.path.dirname(path) |
split结果的个第一元素 |
os.path.basername(path) |
split结果的个第二元素 |
os.path.join(path1, path2, path3 ...) |
把多个路径拼接成一个,并返回 |
os.path.exists(path) |
判断路径是否存在 |
os.path.isabs(path) |
判断路径是否为绝对路径 |
os.path.isfile(path) |
判断路径是否为文件 |
os.path.isdir(path) |
判断路径是否为目录 |
os.path.getatime(path) |
返回文件/目录的最后访问时间。返回值是一个浮点数,为纪元秒数 |
os.path.getctime(path) |
返回文件/目录的最后修改时间。返回值是一个浮点数,为纪元秒数 |
os.path.getmtime(path) |
Unix:返回元数据的最后修改时间,Win:返回创建时间。返回值是一个数,为纪元秒数 |
os.path.size(path) |
返回文件/目录的大小,以字节为单位 |
shutil
shutil模块提供了一系列对文件和文件集合的高阶操作。 特别是提供了一些支持文件拷贝和删除的函数。
拷贝操作
-
shutil.copyfileobj(fsrc, fdst[, length])
将文件类对象 fsrc 的内容拷贝到文件类对象 fdst,length表示缓冲区大小,且默认情况为:1024 * 1024 if WINDOWS else 64 * 1024
。import shutil shutil.copyfileobj(open("./t1/a.txt", "r"), open("t1/b.txt", "w"))
注意有个fsrc是读,而fdst是写
-
shutil.copyfile(src, dst)
将src文件拷贝到dst文件,dst可以不存在import shutil shutil.copyfile("./t1/a.txt", "./t1/b.txt")
-
shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变,此功能并不是在所有平台上均可用(查看文档,了解更多)import shutil shutil.copymode("./t1/a.txt", "./t1/b.txt")
-
shutil.copystat(src, dst)
从 src 拷贝权限位、最近访问时间、最近修改时间以及旗标到 dst. -
shutil.copy(src, dst)
拷贝文件和权限 -
shutil.copy2(src, dst)
拷贝文件和状态信息 -
shutil.copytree(src, dst)
递归拷贝,参数很多,没有详细列出import shutil shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*')) # 目标目录不能存在,注意对folder2目录父级目录要有可写权限,ignore的意思是排除
删除操作
shutil.rmtree(path, ignore_errors=False, onerror=None)
递归删除文件夹。前面说过:空文件夹用os.redir(path),单个文件用os.remove(path);onerror参数可以指定处理程序来处理异常(ignore_errors为False时)
移动操作
shutil.move(src, dst)
递归地将一个文件或目录 (src) 移至另一位置 (dst) 并返回目标位置。同一目录时为重命名,类似于mv命令。
json
json模块可以把python基本数据类型与json数据进行转换。
-
json.dumps(data)
将基本数据类型格式转换为json数据import json data = { "name": "lczmx", "age": 20, } s = json.dumps(data) print(repr(s)) # '{"name": "lczmx", "age": 20}'
-
json.dump(data, file_obj)
将基本数据类型转换为json数据并写入到文件中import json data = { "name": "lczmx", "age": 20, } f = open("./res.json", "w", encoding="utf-8") json.dump(data, f) f.close()
-
json.loads(s)
把json字符串转化为python数据类型import json s = '{"name": "lczmx", "age": 20}' res = json.loads(s) print(res, type(res)) # {'name': 'lczmx', 'age': 20} <class 'dict'>
-
json.load(file_obj)
转换文件对象的json内容。import json with open("./res.json", "r", encoding="utf-8") as f: res = json.load(f) print(res, type(res))
扩展json
json模块只支持python基本数据类型,但我们可以自定义JSON编码器,重写default方法,这样我们自己写的类就可以使用
json.dumps
了
import json
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def data_dict(self):
# 返回的是基本数据类型
return {"name": self.name, "age": self.age}
class JsonCustomEncoder(json.JSONEncoder):
# 重写default方法
def default(self, field):
if isinstance(field, Foo):
return field.data_dict() # 调用自定义的方法
else:
return json.JSONEncoder.default(self, field)
f = Foo("lczmx", 21)
# 使用时要指定自定义的编码器
res = json.dumps(f, cls=JsonCustomEncoder)
print(res)
# {"name": "lczmx", "age": 21}
pickle
模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。
注意:pickle 模块并不安全。你只应该对你信任的数据进行unpickle操作.
import pickle
dic = {'name': 'alvin', 'age': 23, 'sex': 'male'}
print(type(dic)) # <class 'dict'>
j = pickle.dumps(dic)
print(type(j)) # <class 'bytes'>
f = open('序列化对象_pickle', 'wb') # 注意是w是写入str,wb是写入bytes,j是'bytes'
f.write(j) # -------------------等价于pickle.dump(dic,f)
f.close()
# -------------------------反序列化
f = open('序列化对象_pickle', 'rb')
data = pickle.loads(f.read()) # 等价于data=pickle.load(f)
print(data['age'])
shelve
shelve" 是一种持久化的类似字典的对象,只有open方法,比pickle简单。
由于 shelve 模块需要 pickle 的支持,所以shelve模块也不安全。需要注意是否为信任数据才能使用。
import shelve
d = shelve.open("持久化文件.txt")
# 以 d[key] = data 的形式存储
d["name"] = "lczmx"
d["age"] = 22
d["addr"] = "guangzhou"
d["data"] = [1, 2, 3]
# 使用中括号取值
name = d["name"]
print(name) # lczmx
# 使用del删除某个键对应的值
del d["age"]
# 可以使用 in 判断某个键是否存在
flag = "age" in d
print(flag) # False
# .keys()方法 可以列出所有的键 (速度较慢!)
klist = list(d.keys())
print(klist) # ['name', 'addr', 'data']
# 值即使是引用对象,假如要保存修改后的值,要重新赋值
temp = d['data']
temp.append(4)
print(d["data"]) # [1, 2, 3]
d['data'] = temp
print(d["data"]) # [1, 2, 3, 4]
# close掉,可以使用上下文管理协议
d.close()
xml
xml也是一个可以跨语言的数据交换协议,但使用起来没有json简单,由于xml诞生的时间比json早,所以至今还有一些公司正在使用。
生成xml
步骤:
- 创建根节点
- 为根节点添加子节点
- 为字节点添加内容和属性
- 生成文档对象树
- 保存到文件等
import xml.etree.ElementTree as ET
# 创建根节点
new_xml = ET.Element("namelist")
# 为跟节点创建字节点
name1 = ET.SubElement(new_xml, "name", attrib={"enrolled": "yes"})
age1 = ET.SubElement(name1, "age", attrib={"checked": "no"})
# 添加内容
name1.text = '老王'
age1.text = "30"
# 同上
name2 = ET.SubElement(new_xml, "name", attrib={"enrolled": "no"})
age2 = ET.SubElement(name2, "age")
name2.text = "隔壁"
age2.text = '33'
# 生成文档对象
et = ET.ElementTree(new_xml)
# 写入文件中
et.write("test.xml", encoding="utf-8", xml_declaration=True)
# 打印生成的格式
ET.dump(new_xml)
结果:
<?xml version='1.0' encoding='utf-8'?>
<namelist>
<name enrolled="yes">老王<age checked="no">30</age></name>
<name enrolled="no">隔壁<age>33</age></name>
</namelist>
读取xml
对xml文件进行操作,用的是parse
方法和getroot方法
import xml.etree.ElementTree as ET
tree = ET.parse("./test.xml")
root = tree.getroot()
以下都以root即根节点这个对象进行操作
root
可以换成任意子节点
查看
root.tag
获取标签名root.attrib
获取属性root.text
获取内容
遍历/查找
root.iter(tag)
查找子孙节点中的tag标签,以迭代器方式返回root.find(tag)
查找子节点的第一个tag标签root.findall(tag)
找子节点的所有tag标签
修改
root.text="xx"
修改内容root.set("属性名", "属性值")
设置属性值
删除
root.remove(node)
删除子节点
struct
此模块可以执行 Python 值和以 Python bytes 对象表示的 C 结构之间的转换。 这可以被用来处理存储在文件中或是从网络连接等其他来源获取的二进制数据。
一般使用它的两个函数:
struct.pack("格式", data)
struct.unpack("格式", byte_data)
import struct
# 数据 -> bytes
pi = 3.14159265358
res = struct.pack("f", pi)
print(res, type(res)) # b'\xdb\x0fI@' <class 'bytes'> # 已经转化为字节类型
# bytes -> 原数据
data = struct.unpack("f", res)
print(data, type(data)) # (3.1415927410125732,) <class 'tuple'>
格式 | C 类型 | Python 类型 | 标准大小 | 注释 |
---|---|---|---|---|
x | 填充字节 | 无 | ||
c | char | 长度为 1 的字节串 | 1 | |
b | signed char | 整数 | 1 | (1), (2) |
B | unsigned char | 整数 | 1 | (2) |
? | _Bool | bool | 1 | (1) |
h | short | 整数 | 2 | (2) |
H | unsigned short | 整数 | 2 | (2) |
i | int | 整数 | 4 | (2) |
I | unsigned int | 整数 | 4 | (2) |
l | long | 整数 | 4 | (2) |
L | unsigned long | 整数 | 4 | (2) |
q | long long | 整数 | 8 | (2) |
Q | unsigned long long | 整数 | 8 | (2) |
n | ssize_t | 整数 | (3) | |
N | size_t | 整数 | (3) | |
e | (6) | 浮点数 | 2 | (4) |
f | float | 浮点数 | 4 | (4) |
d | double | 浮点数 | 8 | (4) |
s | char[] | 字节串 | ||
p | char[] | 字节串 | ||
P | void * | 整数 | (5) |
re
正则表达式是用来描述字符或字符串的特殊符号,在python中用re模块实现,正则表达式模式被编译成一系列的字节码,用 C 编写的匹配引擎执行。
元字符
正则表达式语言由两种基本字符类型组成:原义(正常)文本字符和元字符,元字符实质上就是有特殊含义的字符。
下面列举一些常用的元字符,参考文档给出的元字符
字符 | 描述 | 列子 |
---|---|---|
\\ |
匹配\ | |
\w |
匹配字母、数字、下划线 | |
\W |
匹配非字母数字下划线 | |
\s |
匹配空白字符 | |
\S |
匹配非空白字符 | |
\d |
匹配数字 | |
\D |
匹配非数字 | |
\n |
匹配换行符 | |
\t |
匹配制表符 | |
^ |
匹配字符串的开头 | |
$ |
匹配字符串的结尾 | |
. |
匹配除换行符外的所有字符,当re.DOTALL标记被指定时,可以匹配换行符 | |
[] |
匹配括号中的每一个字符,如[abc] 表示a 、b 、c |
|
[^] |
匹配不在括号中的字符,如[^abc] 表示不是a 或b |
|
* |
对它前面的正则式匹配0到任意次重复,如\w* 表示0到任意个数字 |
|
+ |
对它前面的正则式匹配1到任意次重复 | |
? |
对它前面的正则式匹配0到1次重复 | |
{n} |
对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败,如\w{6} 表示6个数字 |
|
{n,m} |
对正则式进行 n 到 m 次匹配,在 n 和 m 之间取尽量多。 | |
`a | b` | 匹配a或b |
() |
组合,匹配括号内的表达式 |
更多可以看这篇文章 linux shell 正则表达式(BREs,EREs,PREs)差异比较
关于(?…)个扩展标记法
,可以看官方文档。
方法
查找
使用 | 说明 |
---|---|
re.findall(pattern, string) |
匹配所有结果,返回一个列表,空匹配也会包含在结果里 |
re.finditer(pattern, string) |
匹配所有结果,返回由匹配对象(re.Match )构成的迭代器 。 string 从左到右扫描,匹配按顺序排列。空匹配也包含在结果里。 |
re.search(pattern, string) |
匹配第一个结果,返回匹配对象(re.Match ),未匹配到时为None |
re.match(pattern, string) |
字符串开头相当于re.search("^ ...", string) 是否匹配pattern,是则返回匹配对象(re.Match ),未匹配到时为None |
分割
re.split(pattern, string, maxsplit=0, flags=0)
以pattern规则分割string,结果以列表形式返回,maxsplit非零时,表示分割多少次,flags=re.IGNORECASE可以忽略大小写import re s = "12a21v13xsa15" res = re.split("[a-z]+", s) print(res) # ['12', '21', '13', '15']
替换
- re.sub(pattern, repl, string, count=0, flags=0)
返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串。
可选参数 count 是要替换的最大次数;count 必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换。
假如repl参数是一个函数,那么可以极大扩展替换功能。import re s = "12a21v13xsa15" res = re.sub("[a-z]+", ", ", s) print(res) # 12, 21, 13, 15
import re s = "name=lczmx, age=22" def repl_func(matchobj): age = int(matchobj.group("age")) return str(age + 1) res = re.sub(r"(?P<age>\d+)", repl_func, s) print(res) # name=lczmx, age=23
匹配对象(re.Match
)操作
Match.group([group1, ...])
返回一个或者多个匹配的子组。如果只有一个参数,结果就是一个字符串,如果有多个参数,结果就是一个元组,使用正则表达式使用了(?P<name>…)
语法,可以用Match.group("name")的方式取值。Match.groups(default=None)
返回一个元组,包含所有匹配的子组- Match.groupdict(default=None)¶
返回一个字典,包含了所有的命名子组。key就是组名import re s = "abc@example.com,user" res = re.match(r"([a-zA-Z]+)@(\w+\.com)", s) print(res.groups()) # ('abc', 'example.com') print(res.group(0)) # abc@example.com print(res.group(1)) # abc print(res.group(2)) # example.com res = re.match(r"(?P<prefix>\w+)@(?P<suffix>\w+\.com)", s) print(res.groups()) # ('abc', 'example.com') print(res.group(0)) # abc@example.com print(res.group(1)) # abc print(res.group("prefix")) # abc print(res.group(2)) # example.com print(res.group("suffix")) # example.com print(res.groupdict()) # {'prefix': 'abc', 'suffix': 'example.com'}
去括号优先级
假如这样的例子:
import re
res = re.findall(r"(abc)+", "abcabcabc")
print(res) # ['abc']
其匹配结果是["abc"],而非["abcabcabc"],这是因为括号的优先级高,假如要括号与后面的元字符相结合的化可以使用以下方法:
import re
res = re.findall(r"(?:abc)+", "abcabcabc")
print(res) # ['abcabcabc']
匹配原理
关于正则匹配原理,看此文。
logging
关于日志管理的基本教程,请点击这里
关于使用日志的流程,大约有以下步骤:
- 调用
logging.basicConfig()
设置logging
,确定日记级别、是否输入到文件、信息格式等参数 - 根据需求,调用
logging
的debug
、info
、warning
、error
、critical
方法
注意
由于logging.basicConfig()只需要定义一次,所以debug
等方法应该在其被设置后调用
格式
format参数指定日志的格式, 形如:
logging.basicConfig(level = logging.DEBUG,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
%(levelno)s:打印日志级别的数值
%(levelname)s:打印日志级别的名称
%(pathname)s:打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s:打印当前执行程序名
%(funcName)s:打印日志的当前函数
%(lineno)d:打印日志的当前行号
%(asctime)s:打印日志的时间
%(thread)d:打印线程ID
%(threadName)s:打印线程名称
%(process)d:打印进程ID
%(message)s:打印日志信息
打印到终端
打印到终端是开发过程中的一个实用的方法。
import logging
logging.basicConfig()
logging.debug("debug messages")
logging.info("info messages")
logging.warning("warning messages")
logging.error("error messages")
logging.critical("critical messages")
由于默认日志级别为WARNING,所以只在终端显示了后三行信息
写入文件
为basicConfig()
增加filename
参数即可
import logging
logging.basicConfig(filename="test.log")
logging.debug("debug messages")
logging.info("info messages")
logging.warning("warning messages")
logging.error("error messages")
logging.critical("critical messages")
python 3.9版本的logging.basicConfig() 可以指定
encoding
参数,之前的以系统默认的编码方式打开。
多模块使用
在多个模块中import logging
即可,其操作的是同一个logging对象
import logging
import mylib
def main():
logging.basicConfig()
logging.warning("start function")
mylib.my_func()
logging.warning("end function")
print(id(logging)) # 2248755624272
if __name__ == '__main__':
main()
./mylib.py
# ./mylib.py
import logging
def my_func():
logging.error("error massage")
print(id(logging)) # 2248755624272
修改日志级别
日志级别从低到高:
级别 | 何时使用 |
---|---|
DEBUG | 细节信息,仅当诊断问题时适用。 |
INFO | 确认程序按预期运行 |
WARNING | 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行 |
ERROR | 由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL | 严重的错误,表明程序已不能继续执行 |
默认级别为WARNING
修改日志级别要用到logging.basicConfig()
的level
参数,其传入的值是一个在logging模块中已经被定义好的数:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
例子:
import logging
logging.basicConfig(level=logging.INFO)
logging.warning("start function")
从命令行中接收日志级别
使用argparse
库接收命令行参数,再使用getattr()
方法从logging
模块中把对应的日志级别取出来:
import logging
import argparse
# log选项的值只能是level_list的元素
level_list = ["debug", "info", "warning", "warn", "error", "fatal", "critical"]
level_list.extend(list(map(lambda x: x.upper(), level_list))) # 全大写再加入
parser = argparse.ArgumentParser(description="test file")
parser.add_argument("--log", default="debug", choices=level_list)
args = parser.parse_args()
# 拿到级别字符串后要大写
level = getattr(logging, args.log.upper())
logging.basicConfig(level=level)
logging.debug("debug messages")
logging.info("info messages")
logging.warning("warning messages")
logging.error("error messages")
logging.critical("critical messages")
$ python test.py --log error
ERROR:root:error messages
CRITICAL:root:critical messages
$ python test.py --log info
INFO:root:info messages
WARNING:root:warning messages
ERROR:root:error messages
CRITICAL:root:critical messages
configparser
configparser库是python的配置文件管理模块,其所用结构与 INI 文件的类似。
注意:小节(section)中的键(key)大小写不敏感并且会存储为小写形式
写
步骤:
- 创建对象
configparser.ConfigParser()
- 在字典中添加数据,用中括号操作,类似字典
- 写入文件
import configparser
# 1 创建parser对象
config = configparser.ConfigParser()
# 2 添加数据
# 方法一
config["DEFAULT"] = {"HOST": "localhost", "PORT": "3306"}
# 方法二
config["CUSTOM"] = {}
config["CUSTOM"]["HOST"] = "192.168.0.1"
# 或
custom_config = config["CUSTOM"]
custom_config["PORT"] = "3333"
# 3 写入文件
with open("config.ini", "w") as f:
config.write(f)
最外层就是一个字典
config.ini文件:
[DEFAULT]
host = localhost
port = 3306
[CUSTOM]
host = 192.168.0.1
port = 3333
读
注意:DEFAULT不在sections()中,可以直接用["DEFAULT"].get(key)
或.get("DEFAULT", key)
取值
根据不同的需求可以用以下几个方法:
-
config.read(path) 读取配置文件
-
config.sections() 返回可用节的列表,即
[xxx]
中的xxx
-
config.options(Section) 返回键构成的元组
-
config.items(Section) 返回列表,元素为键值对组成的元组
-
config.get(Section, key) 等价于 Section.get(key)
-
Section.get(key, default) 类似字典一样取值
config 还可以通过使用for循环,有.keys(), .values(), .items()
import configparser config = configparser.ConfigParser() config.read("./config.ini") print(config["DEFAULT"].get("host")) # localhost print(config.options("CUSTOM")) # ['host', 'port'] print(config.items("CUSTOM")) # [('host', '192.168.0.1'), ('port', '3333')]
删操作
-
config.remove_section(section) 删除块即整个
[xxx]
-
config.remove_option(section, key) 删除块下面的键(包括值)
import configparser config = configparser.ConfigParser() config.read("./config.ini") config.remove_section("CUSTOM") config.remove_option("DEFAULT", "host") config.write(open("./config.ini", "w"))
argparse
argparse是python推荐的命令行参数解析模块,argparse基于optparse(3.2版中已经被弃用),所以两者用法类似。
其一般的使用步骤是:
- 创建解析器
- 添加参数
- 解析参数
创建解析器
parser = argparse.ArgumentParser(description="计算两个数的和", prog="SUM")
description
参数可以指定帮助文档之前显示的描述信息prog
指定程序名,默认sys.argv[0]
添加参数
使用parser.add_argument(name or flags)
方法,该方法可以指定位置参数或者是选项,而且它可以接收很多参数,下面列举几个常用的参数:
- action - 当参数在命令行中出现时使用的动作基本类型。
它的值列出这几个更多可以看文档:action值 说明 store
存储参数的值(默认) store_true
andstore_false
分别用作存储 True 和 False 值的特殊用例 version
期望有一个 version= 命名参数,version参数可以用 %(prog)s
的形式使用prog参数 - default - 设置默认值。
- type - 命令行参数应当被转换成的类型,即把str转成其他形式。
- choices - 可用的参数的容器(一般为列表),即参数值只能是里面的元素。
- required - 此命令行选项是否必需,默认
False
(一般来说选项是可以被省略的,不然换为位置参数更好)。 - help - 为此选项作用的简单描述,使用-h或--help可以看到。
parser.add_argument("x", type=float, help="一个数x") # 添加位置参数x
parser.add_argument("y", type=float, help="一个数y") # 添加位置参数y
# 添加选项-a, 把值存储为True
parser.add_argument("-a", action="store_true", help="显示详细过程")
# 添加选项-f,它的值知道能是[1, 2, 3]中的元素
parser.add_argument("-f", default=1, choices=[1, 2, 3],
type=int, help="保留小数点位数")
# 添加选项-v 或 --version
# 使用来自argparse.ArgumentParser的prog参数
parser.add_argument("-v", "--version", action="version",
version="%(prog)s 0.1", help="显示版本")
解析参数
通过parser.parse_args()
解析,然后通过.
的方式取值(无论位置参数还是选项)
# 解析
args = parser.parse_args()
print(args.x)
print(args.a)
print(args.f)
完整例子
一个计算两个数和的程序
import argparse
parser = argparse.ArgumentParser(description="计算两个数的和", prog="SUM")
parser.add_argument("x", type=float, help="一个数x") # 添加位置参数x
parser.add_argument("y", type=float, help="一个数y") # 添加位置参数y
# 添加选项-a, 把值存储为True
parser.add_argument("-a", action="store_true", help="显示详细过程")
# 添加选项-f,它的值知道能是[1, 2, 3]中的元素
parser.add_argument("-f", default=1, choices=[1, 2, 3],
type=int, help="保留小数点位数")
# 添加选项-v 或 --version
# 使用来自argparse.ArgumentParser的prog参数
parser.add_argument("-v", "--version", action="version",
version="%(prog)s 0.1", help="显示版本")
# 解析
args = parser.parse_args()
# 计算并保留小数
res = round(args.x + args.y, args.f)
if args.a:
print("{x} + {y} = {res}".format(x=args.x, y=args.y, res=res))
else:
print(res)
在命令行中使用:
$ python get_sum.py -h
usage: SUM [-h] [-a] [-f {1,2,3}] [-v] x y
计算两个数的和
positional arguments:
x 一个数x
y 一个数y
optional arguments:
-h, --help show this help message and exit
-a 显示详细过程
-f {1,2,3} 保留小数点位数
-v, --version 显示版本
$ python get_sum.py -v
SUM 0.1
$ python get_sum.py 3.14 5.96
9.1
$ python get_sum.py 3.14 5.96 -a
3.14 + 5.96 = 9.1
$ python get_sum.py 3.14159 3.335 -f 3 -a
3.14159 + 3.335 = 6.477
$ python get_sum.py
usage: SUM [-h] [-a] [-f {1,2,3}] [-v] x y
SUM: error: the following arguments are required: x, y
hashlib
hashlib是针对不同的安全哈希和消息摘要算法实现了一个通用的接口。
生成md5
import hashlib
md5 = hashlib.md5()
# 输入的是字节串
md5.update("test message".encode("utf-8"))
res = md5.hexdigest()
print(res)
# c72b9698fa1927e1dd12d3cf26ed84b2
为md5加盐
所谓加盐就是update其他内容,改变md5的值,防止撞库。
import hashlib
md5 = hashlib.md5()
# 输入的是字节
md5.update("加盐".encode("utf-8"))
md5.update("test message".encode("utf-8"))
res = md5.hexdigest()
print(res)
# 3f5a030db81d9e5e83d2c8e7eba1965c
uuid
生成uuid4
import uuid
print(uuid.uuid4())
# f1d50cdd-2f36-4db2-b788-ec4f2f08ce52
subprocess
subprocess 模块允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。
对于subprocess模块,我们只需要关注底层的Popen接口的使用方法即可。
常用参数:
args
一般来说是命令,推荐使用列表的方式传入(有顺序)shell
True或False
在 POSIX,当 shell=True, shell 默认为/bin/sh
在 Windows,当 shell=True,环境变量 COMSPEC 指定了默认 shell,执行命令时可以为True,但执行批处理文件或可执行文件时,不需要shell=Truestdin
,stdout
和stderr
分别指定了执行的程序的标准输入、输出和标准错误文件句柄
它们的合法值一般有:- 其他Popen对象的stdin/stdout/stderr
subprocess.PIPE
表示打开标准流的管道None
- 文件对象
更加详细内容,请看官方文档
获取返回信息
- 使用
subprocess.PIPE
接收 - popen_obj.stdout.read().decode("xx") 的方式
当然也可以在stdout中传入文件对象,直接写入文件中
使用例子
import subprocess
# 执行没有参数的
subprocess.Popen(["dir"], shell=True, stdout=open("dir_res.txt", "w"))
# 有参数
# get_sum.py为argparse模块最后的例子
command = "python get_sum.py 3.47 2.48 -a -f 2"
res2 = subprocess.Popen(command.split(" "), shell=True, stdout=subprocess.PIPE)
print(res2.stdout.read().decode("gbk")) # 3.47 + 2.48 = 5.95
# stdout作为stdin
res3 = subprocess.Popen(["echo", "www.baidu.com"],
shell=True, stdout=subprocess.PIPE)
res4 = subprocess.Popen(["nslookup"], shell=True,
stdin=res3.stdout, stdout=subprocess.PIPE)
print(res4.stdout.read().decode("gbk"))
"""
默认服务器: UnKnown
Address: 192.168.0.1
> 服务器: UnKnown
Address: 192.168.0.1
名称: www.baidu.com
Address: 182.61.200.7
>
"""
num1 > num2时为[num2, num1] ↩︎
本文来自博客园,作者:403·Forbidden,转载请注明原文链接:https://www.cnblogs.com/lczmx/p/14323131.html