主頁 > 後端開發 > python3常用標準庫

python3常用標準庫

2021-01-25 06:14:00 後端開發

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

time庫各方法關系
time庫各方法關系

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模塊提供了一系列對檔案和檔案集合的高階操作, 特別是提供了一些支持檔案拷貝和洗掉的函式,

拷貝操作

  1. 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是寫

  2. shutil.copyfile(src, dst)
    將src檔案拷貝到dst檔案,dst可以不存在

    import shutil
    
    
    shutil.copyfile("./t1/a.txt", "./t1/b.txt")
  3. shutil.copymode(src, dst)
    僅拷貝權限,內容、組、用戶均不變,此功能并不是在所有平臺上均可用(查看檔案,了解更多)

    import shutil
    
    
    shutil.copymode("./t1/a.txt", "./t1/b.txt")
  4. shutil.copystat(src, dst)
    從 src 拷貝權限位、最近訪問時間、最近修改時間以及旗標到 dst.

  5. shutil.copy(src, dst)
    拷貝檔案和權限

  6. shutil.copy2(src, dst)
    拷貝檔案和狀態資訊

  7. shutil.copytree(src, dst)
    遞回拷貝,引數很多,沒有詳細列出

    import shutil
    
    shutil.copytree('folder1', 'folder2',
    				ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))
    # 目標目錄不能存在,注意對folder2目錄父級目錄要有可寫權限,ignore的意思是排除

洗掉操作

  • shutil.rmtree(path, ignore_errors=False, one rror=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 = https://www.cnblogs.com/lczmx/p/{
    	"name": "lczmx",
    	"age": 20,
    }
    
    s = json.dumps(data)
    
    print(repr(s))  # '{"name": "lczmx", "age": 20}'
  • json.dump(data, file_obj)
    將基本資料型別轉換為json資料并寫入到檔案中

    import json
    
    data = https://www.cnblogs.com/lczmx/p/{
    	"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 = https://www.cnblogs.com/lczmx/p/pickle.loads(f.read())  # 等價于data=https://www.cnblogs.com/lczmx/p/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

步驟:

  1. 創建根節點
  2. 為根節點添加子節點
  3. 為位元組點添加內容和屬性
  4. 生成檔案物件樹
  5. 保存到檔案等
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 結構之間的轉換, 這可以被用來處理存盤在檔案中或是從網路連接等其他來源獲取的二進制資料,
一般使用它的兩個函式:

  1. struct.pack("格式", data)
  2. 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 = https://www.cnblogs.com/lczmx/p/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]表示abc
[^] 匹配不在括號中的字符,如[^abc]表示不是ab
* 對它前面的正則式匹配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<name>…) 語法,可以用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]
    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]
    
    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

關于日志管理的基本教程,請點擊這里

關于使用日志的流程,大約有以下步驟:

  1. 呼叫logging.basicConfig()設定logging,確定日記級別、是否輸入到檔案、資訊格式等引數
  2. 根據需求,呼叫loggingdebuginfowarningerrorcritical方法

注意
由于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)大小寫不敏感并且會存盤為小寫形式

步驟:

  1. 創建物件configparser.ConfigParser()
  2. 在字典中添加資料,用中括號操作,類似字典
  3. 寫入檔案
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版中已經被棄用),所以兩者用法類似,
其一般的使用步驟是:

  1. 創建決議器
  2. 添加引數
  3. 決議引數

創建決議器

 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
  • stdinstdoutstderr
    分別指定了執行的程式的標準輸入、輸出和標準錯誤檔案句柄
    它們的合法值一般有:
    1. 其他Popen物件的stdin/stdout/stderr
    2. subprocess.PIPE 表示打開標準流的管道
    3. None
    4. 檔案物件

更加詳細內容,請看官方檔案

獲取回傳資訊

  1. 使用subprocess.PIPE接收
  2. 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

>
"""

我的github
我的博客
我的筆記


  1. num1 > num2時為[num2, num1] ?

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251951.html

標籤:Python

上一篇:Python 日志列印之自定義logger handler

下一篇:全網最詳細的PyCharm+Anaconda的安裝。

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more