1. 程式人生 > 實用技巧 >17.xml模組、hashlib模組、subprocess模組、os與sys模組、configparser模組

17.xml模組、hashlib模組、subprocess模組、os與sys模組、configparser模組

  • 引子
  • xml模組

  • hashlib模組

  • subprocess模組

  • os與sys模組

  • configparser模組


  • xml模組

    xml是實現不同語言或程式之間進行資料交換的協議,跟json差不多,但json使用起來更簡單,不過,古時候,
    在json還沒誕生的黑暗年代,大家只能選擇用xml呀,至今很多傳統公司如金融行業的很多系統的介面還主要是xml。
xml的格式如下,就是通過<>節點來區別資料結構的:
<?xml version="1.0"?>
<data>
    <country name="Liechtenstein">
        <rank updated="yes">2</rank>
        <year>2008</year>
        <gdppc>141100</gdppc>
        <neighbor name="Austria" direction="E"/>
        <neighbor name="Switzerland" direction="W"/>
    </country>
    <country name="Singapore">
        <rank updated="yes">5</rank>
        <year>2011</year>
        <gdppc>59900</gdppc>
        <neighbor name="Malaysia" direction="N"/>
    </country>
    <country name="Panama">
        <rank updated="yes">69</rank>
        <year>2011</year>
        <gdppc>13600</gdppc>
        <neighbor name="Costa Rica" direction="W"/>
        <neighbor name="Colombia" direction="E"/>
    </country>
</data>

xml資料
xml協議在各個語言裡的都 是支援的,在python中可以用以下模組操作xml:
# print(root.iter('year'))  # 全文搜尋
# print(root.find('country'))  # 在root的子節點找,只找一個
# print(root.findall('country'))  # 在root的子節點找,找所有

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
 
#遍歷xml文件
for child in root:
    print('========>',child.tag,child.attrib,child.attrib['name'])
    for i in child:
        print(i.tag,i.attrib,i.text)
 
#只遍歷year 節點
for node in root.iter('year'):
    print(node.tag,node.text)
#---------------------------------------

import xml.etree.ElementTree as ET
 
tree = ET.parse("xmltest.xml")
root = tree.getroot()
 
#修改
for node in root.iter('year'):
    new_year=int(node.text)+1
    node.text=str(new_year)
    node.set('updated','yes')
    node.set('version','1.0')
tree.write('test.xml')
 
 
#刪除node
for country in root.findall('country'):
   rank = int(country.find('rank').text)
   if rank > 50:
     root.remove(country)
 
tree.write('output.xml')
#在country內新增(append)節點year2
import xml.etree.ElementTree as ET
tree = ET.parse("a.xml")
root=tree.getroot()
for country in root.findall('country'):
    for year in country.findall('year'):
        if int(year.text) > 2000:
            year2=ET.Element('year2')
            year2.text='新年'
            year2.attrib={'update':'yes'}
            country.append(year2) #往country節點下新增子節點

tree.write('a.xml.swap')
自己建立xml文件:
import xml.etree.ElementTree as ET
 
 
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
 
et = ET.ElementTree(new_xml) #生成文件物件
et.write("test.xml", encoding="utf-8",xml_declaration=True)
 
ET.dump(new_xml) #列印生成的格式

  • hashlib模組

    hash演算法:傳入一段內容會得到一串hash值

    hash值有三大特點:

    1.如果傳入的內容與採用的演算法一樣,那麼得到的hash值一定一樣
    2.只要採用的演算法是固定的,hash值的長度就是固定的,不會隨著內容的增多而變長
    3.hash值不可逆,即不能通過hash值反解出內容是什麼
    1 + 2 = 》效驗檔案的完整性
    1 + 3 = 》加密
# 傳入的內容與採用的演算法一樣,得到的hash值一定一樣
import hashlib

m = hashlib.md5()
m.update("你好".encode('utf-8'))
m.update("hello".encode('utf-8'))
m.update("哈哈".encode('utf-8'))

# "你好hello哈哈"   # hash工廠計算的是它的值
print(m.hexdigest())  # 43b2fa0da902a2d9175fb4d4b858e5d5

m1 = hashlib.md5()
m1.update("你".encode('utf-8'))
m1.update("好hello".encode('utf-8'))
m1.update("哈".encode('utf-8'))

# "你好hello哈哈"
print(m1.hexdigest())  # 43b2fa0da902a2d9175fb4d4b858e5d5




# 效驗檔案完整性
import hashlib
m = hashlib.md5()

with open(r'D:\python17\day16\程式碼.zip',mode='rb') as f:
    for line in f:
        m.update(line)
    res = m.hexdigest()
    print(res)

    
    
import hashlib
m = hashlib.md5()

m.update("天王".encode('utf-8'))   # 密碼加鹽
m.update("123egon".encode('utf-8'))
m.update("蓋地虎".encode('utf-8'))
print(m.hexdigest())

  • subprocess模組

    即允許你去建立一個新的程序讓其執行另外的程式,並與它進行通訊,
    獲取標準的輸入、標準輸出、標準錯誤以及返回碼等。

    注意:使用這個模組之前要先引入該模組。

    Popen類

    subprocess模組中定義了一個Popen類,通過它可以來建立程序,並與其進行復雜的互動。

import subprocess
import time
# “Tasklist”命令是一個用來檢視執行在本地或遠端計算機上的所有程序的命令列工具,帶有多個執行引數。
# Popen 等同於cmd.exe命令直譯器
obj = subprocess.Popen("tasklist",
                       # shell=True等同於呼叫命令直譯器
                       shell=True,
                       # 管道記憶體正確輸出結果
                       stdout=subprocess.PIPE,
                       # 管道記憶體錯誤輸出結果
                       stderr=subprocess.PIPE
                       )

print("=============>", obj) # 拿到的是subprocess的物件
# =============> <subprocess.Popen object at 0x00000193E7E04BB0>

# 主程序從管道拿到子程序結果
stdout_res = obj.stdout.read()
stderr_res = obj.stderr.read()

# subprocess使用當前系統預設編碼,得到結果為bytes型別,在windows下需要用gbk解碼
print(stdout_res.decode('gbk'))
print(stderr_res.decode('gbk'))


# 主程序想拿到子程序執行命令的結果做進一步的處理
# 每啟動一個程序在記憶體裡佔用一個記憶體空間,程序與程序之間的記憶體空間是相互隔離的
# 在子程序執行Tasklist這條命令,執行完之後這條命令的結果一定是產生在子程序的記憶體空間裡
# 不可能在主程序拿到這個結果,這個就要用到共享記憶體了,即“管道”
  • os與sys模組

  • os模組

    這個模組提供了一種方便的bai使用作業系統函du數的方法。
    os模組負責程式與作業系統的互動,提供了訪問作業系統底層的介面
os.getcwd() 獲取當前工作目錄,即當前python指令碼工作的目錄路徑
os.chdir("dirname")  改變當前指令碼工作目錄;相當於shell下cd
os.curdir  返回當前目錄: ('.')
os.pardir  獲取當前目錄的父目錄字串名:('..')
os.makedirs('dirname1/dirname2')    可生成多層遞迴目錄
os.removedirs('dirname1')    若目錄為空,則刪除,並遞迴到上一級目錄,如若也為空,則刪除,依此類推
os.mkdir('dirname')    生成單級目錄;相當於shell中mkdir dirname
os.rmdir('dirname')    刪除單級空目錄,若目錄不為空則無法刪除,報錯;相當於shell中rmdir dirname
os.listdir('dirname')    列出指定目錄下的所有檔案和子目錄,包括隱藏檔案,並以列表方式列印
os.remove()  刪除一個檔案
os.rename("oldname","newname")  重新命名檔案/目錄
os.stat('path/filename')  獲取檔案/目錄資訊
os.sep    輸出作業系統特定的路徑分隔符,win下為"\\",Linux下為"/"
os.linesep    輸出當前平臺使用的行終止符,win下為"\t\n",Linux下為"\n"
os.pathsep    輸出用於分割檔案路徑的字串 win下為;,Linux下為:
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所指向的檔案或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小
os的用法演示
import os

print(os.getcwd()) # 獲取當前工作所在資料夾
os.makedirs("a/b/c") # 遞迴建立資料夾
os.removedirs("a/b/c") # 遞迴刪除資料夾

res = os.listdir('.') # 瀏覽當前資料夾列表顯示
print(res)

print(os.stat("今日內容.txt")) # 檢視檔案資訊

print(os.path.getsize("今日內容.txt")) # 獲取檔案的大小以位元組顯示

print(os.environ)  # 環境變數
os.environ["name"] = "egon"
print(os.environ)
print(os.environ['name'])

 
print(os.path.abspath("a/b/c"))   # 返回path規範化的絕對路徑
print(os.path.split(r"D:\a\b\c\d.txt")) # 
print(os.path.dirname(r"D:\a\b\c\d.txt"))
print(os.path.basename(r"D:\a\b\c\d.txt"))

res = os.path.exists(r"D:\a\b")
print(res)

print(os.path.isabs(r"D:\a\b\c\d.txt"))
print(os.path.isabs(r"c\d.txt"))

print(os.path.join("D:",'a',"b","c.txt"))


# os路徑處理
# 方式一:
#     獲取路徑資料夾---》獲取當前資料夾的上一級資料夾
print(os.path.dirname(os.path.dirname(__file__)))

# 方式二:
res = os.path.normpath(os.path.join(__file__,"..",'..'))
print(res)

  • sys模組

    這個模組可供訪問由直譯器使用或維護的變數和與直譯器進行互動的函
    sys模組負責程式與python直譯器的互動,提供了一系列的函式和變數,用於操控python的執行時環境
1 sys.argv           命令列引數List,第一個元素是程式本身路徑
2 sys.exit(n)        退出程式,正常退出時exit(0)
3 sys.version        獲取Python解釋程式的版本資訊
4 sys.maxint         最大的Int值
5 sys.path           返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值
6 sys.platform       返回作業系統平臺名稱


import sys

# print(sys.argv)  # sys.argv 從命令列中接收使用者輸入

src_file = sys.argv[1]
dst_file = sys.argv[2]

with open(r'%s' %src_file,mode='rb') as f1,\
    open(r'%s' %dst_file,mode='wb') as f2:
    for line in f1:
        f2.write(line)

列印進度條
#=========知識儲備==========
#進度條的效果
[#             ]
[##            ]
[###           ]
[####          ]

#指定寬度
print('[%-15s]' %'#')
print('[%-15s]' %'##')
print('[%-15s]' %'###')
print('[%-15s]' %'####')

#列印%
print('%s%%' %(100)) #第二個%號代表取消第一個%的特殊意義

#可傳參來控制寬度
print('[%%-%ds]' %50) #[%-50s]
print(('[%%-%ds]' %50) %'#')
print(('[%%-%ds]' %50) %'##')
print(('[%%-%ds]' %50) %'###')


#=========實現列印進度條函式==========
import sys
import time

def progress(percent,width=50):
    if percent >= 1:
        percent=1
    show_str=('[%%-%ds]' %width) %(int(width*percent)*'#')
    print('\r%s %d%%' %(show_str,int(100*percent)),file=sys.stdout,flush=True,end='')


#=========應用==========
data_size=1025
recv_size=0
while recv_size < data_size:
    time.sleep(0.1) #模擬資料的傳輸延遲
    recv_size+=1024 #每次收1024

    percent=recv_size/data_size #接收的比例
    progress(percent,width=70) #進度條的寬度70


  • configparser模組

    該模組適用於配置檔案的格式與windows ini檔案類似,可以包含一個或多個節(section),
    每個節可以有多個引數(鍵=值)。節與java原先的配置檔案相同的格式
  • 配置檔案:
# config.ini 配置檔案

# 註釋1
; 註釋2

[mysqld]   # 標題
k1 = v1    # 配置項 key:value的形式
k2:v2
user=egon
age=18
is_admin=true
salary=31
log_path = D:\a\b\c.log

[client]
k1 = v1
  • 解析配置檔案
# configparser模組  #  用來解析配置檔案的

import configparser

config = configparser.ConfigParser()  # 返回一個物件
config.read('config.ini') #,用這個物件執行.read(配置檔案)

res = config.sections()  # 拿到config.ini配置檔案下所有的標題
print(res)

res = config.options('mysqld') # 拿到標題mysqld下所有配置項key=value的key

res = config.items('mysqld') # 拿到標題mysqld下所有配置項key=value的(key,value)格式
print(res)

res = config.get('mysqld', 'log_path') # 指定拿到標題mysqld下log_path日誌的路徑
print(res)

res = config.getint('mysqld', 'age') # 拿到標題mysqld下age的值=>整數格式

res = config.getboolean('mysqld', 'is_admin') #拿到標題mysqld下is_admin的值=>布林值格式
print(res,type(res))

res = conf.getfloat('mysqld','salary') # 拿到標題mysqld下salary的值=>浮點型格式
print(res)