1. 程式人生 > 其它 >python3常用標準庫

python3常用標準庫

技術標籤:python基礎教程python基礎教程

趁著有時間,把一些我用過的常用標準庫進行整理和複習。

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
time庫各方法關係
time庫各方法關係
datetime
雖然python庫中已經有了time庫,但time庫不支vb.net教程

持對時間的加減等操作,因此就有了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物件的方法,可以替c#教程換當前物件的year等屬性,詳見文件
有了以上幾個方法,我們就可以對時間進行加減操作,並可以在time和datetime之間進行轉換。

datetime.datetime之間可以相減,結果為datetime.timedelta物件,有days和seconds屬性
datetime.datetime與datetime.timedelta之間可以加減,結果為datetime.datetime物件
datetime.timedelta本身可以乘以一個數,以表示不同的時間python基礎教程間隔

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, οnerrοr=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\[email protected]' <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,所有的匹配都會被替換。

import re

s = "12a21v13xsa15"
res = re.sub("[a-z]+", ", ", s)

print(res)  # 12, 21, 13, 15

假如repl引數是一個函式,那麼可以極大擴充套件替換功能。

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…) 語法,可以用Match.group(“name”)的方式取值。
Match.groups(default=None)
返回一個元組,包含所有匹配的子組
Match.groupdict(default=None)¶
返回一個字典,包含了所有的命名子組。key就是組名

import re

s = "[email protected],user"

res = re.match(r"([a-zA-Z]+)@(\w+\.com)", s)


print(res.groups())  # ('abc', 'example.com')
print(res.group(0))  # [email protected].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))  # [email protected].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等方法應該在其被設定後呼叫

列印到終端
列印到終端是開發過程中的一個實用的方法。

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 and store_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=True
stdin, 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

>