1. 程式人生 > >Python-常用模組2

Python-常用模組2

  今天我們繼續來看模組的那些事兒

一.os模組

  所有和作業系統相關內容都在os模組

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.system('bash command')  執行shell命令,直接顯示
os.popen('bash command').read()  執行shell命令,獲取執行結果
os.getcwd() 獲取當前工作目錄,即當前python指令碼工作的目錄路徑
os.chdir('dirname') 改變當前指令碼工作目錄;相當於shell下cd

#os.path
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.pathjoin(path1[,path2[,...]]) 將多個路徑組合後返回,第一個絕對路徑之前的引數將被忽略
os.path.getatime(path) 返回path所指向的檔案或者目錄的最後訪問時間
os.path.getmtime(path) 返回path所指向的檔案或者目錄的最後修改時間
os.path.getsize(path) 返回path的大小

#特殊屬性
os.sep 輸出作業系統特定的路徑分隔符,win下為'\\',Linux下為'/'
os.linesep 輸出當前平臺使用的行為終止符,win下為'\r\n',Linux下'\n'
os.pathsep 輸出用於分割檔案路徑的字串 win下為;,Linux下為:
os.name 輸出字串指示當前使用平臺,win -> 'nt' ; Linux -> 'posix'

  os.stat() 屬性解讀:

stat結構:

st_mode:inode保護模式
st_ino:inode 節點號
st_dev:inode 駐留的裝置
st_nlink: inode 的連結數
st_uid:所有者的使用者ID
st_gid:所有者的組ID
st_size: 普通檔案以位元組為單位的大小;包含等待某些特殊檔案的資料
st_atime:上次訪問的時間
st_mtime:最後一次修改的時間
st_ctime:由作業系統報告的'ctime',在某些系統上(如Unix)是最新的元資料更改的時間,在其他系統上(如Windows) 是建立時間(詳細資訊參見平臺的文件)

二.sys模組

  所有和python直譯器相關的都在sys模組

sys.argv  命令列引數list,第一個元素是程式本身路徑
sys.exit(n) 退出程式,正常退出時exit(0),錯誤退出sys.exit(1)
sys.version  獲取python解釋程式的版本資訊
sys.path     返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數值
sys.platform   返回作業系統平臺名稱

三.序列化

  在我們儲存資料或者網路傳輸資料的時候,需要對我們的物件進行處理,把物件處理成方便儲存和傳輸的資料格式,這個過程叫序列化,不同的序列化結果也不同,但是目的是一樣的,都是為了儲存和傳輸

  在python中存在兩種序列化大方案:

    1.pickle,可以將我們Python中的任意資料型別轉化成bytes並寫入檔案中,同樣也可以把檔案中寫好的bytes轉換回我們python的資料,這個過程被稱為反序列化

    2.json,將python中常見的字典,列表轉化成 字串,是目前前後端資料互動使用頻率最高的一種資料格式.

四.pickle(重點)

  pickle用起來很簡單,說白了就是把我們的python物件寫入到檔案中的一種解決方案,但是寫入到檔案的是bytes,所以這東西不是給人看的,是給機器看到

import pickle

class Cat:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def catchMouse(self):
        print(self.name,'抓老鼠')
c = Cat('jerry',18)

bs = pickle.dumps(c)  #序列化一個物件
print(bs)  #一堆二進位制,看不懂

cc = pickle.loads(bs)  #把二進位制反序列化成我們的物件
cc.catchMouse()  #貓依然是貓,還可以抓老鼠

  pickle中的dumps可以序列化一個物件,loads可以反序列化一個物件,我們使用dump還可以直接把一個物件寫入到檔案中

#f = open('cat',mode = 'wb')
#pickle.dump(c,f) #寫入到檔案中
#f.close()

f = open('cat',mode = 'rb')
cc = pickle.load(f)  #從檔案中讀取物件
cc.catchMouse()

  pickle還支援多個物件的寫出:

lst = [Cat('jerry',19),Cat('tommy',20),Cat('alpha',21)]

f = open('cat',mode = 'wb')
for el in lst:
    pickle.dump(el,f)  #寫入到檔案中
f.close()

f = open('cat',mode = 'rb')
for i in range(len(lst)):
    cc = pickle.load(f)  #從檔案中讀取物件
    cc.catchMouse()

  但是這樣寫並不夠好,因為讀的時候並不能知道有多少物件要讀,這裡記住,不能一行一行的讀,那真的要寫入或者讀取多個內容怎麼辦?很簡單,裝列表裡,然後讀取和寫入都用列表

lst = [Cat('jerry',19),Cat('tommy',20),Cat('alpha',21)]

f = open('cat',mode = 'wb')
pickle.dump(lst,f)

f = open('cat',mode = 'rb')
l1 = pickle.load(f)
for el in l1:
    el.catchMouse()

  記住一點,pickle序列化的內容是二進位制的內容(bytes)不是給人看的

五.json(重點)

  終於到json了,json是我們前後端互動的樞紐,相當於程式設計界的普通話,大家溝通都用json,為什麼這樣呢?因為json的語法格式可以完美的表示出一個物件,那什麼是json:json全稱javascript object notation,翻譯過來叫js物件簡譜,很複雜是吧.來上一段我們認識的程式碼:

wf = {
        'name':'汪峰',
        'age':18,
        'hobby':'上頭條',
        'wife':{
            'name':'子怡',
            'age':19,
            'hobby':['唱歌','跳舞','演戲']
    }
}

  這個不是字典麼?對的,在Python裡這玩意叫字典,但是在javascript裡這東西叫json,一模一樣的,我們發現用這樣的資料結構可以完美的表示出任何物件,並且可以完整的把物件表示出來,只要程式碼格式比較好,那可讀性也是很強的,所以大家公認用這樣一種資料結構作為資料互動的格式,那這個鬼東西之前是什麼呢?XML...來看一段程式碼:

<?xml version="1.0" encoding="utf-8" ?>
<wf>
    <name>汪峰</name>
    <age>18</age>
    <hobby>上頭條</hobby>
    <wife>
        <name>⼦怡</name>
        <age>18</age>
        <hobbies>
            <hobby>唱歌</hobby>
            <hobby>跳舞</hobby>
            <hobby>演戲</hobby>
        </hobbies>
    </wife>
 
</wf>

  古人(老程式設計師)都是用這樣的資料進行傳輸的,先不管這個東西好不好看,這玩意想要解析.. 那簡直了. 想死的心都有,所以老版本的xml在維護和處理上是非常複雜和繁瑣的,多說一嘴, 就是因為這個鬼東西太難解析,以前的專案幾乎沒有用ajax的. 

  OK,那json既然這麼牛B好用, 怎麼用呢? 注意,這裡又出來一個新問題,我們的程式是在python裡寫的,但是前端是在JS那邊來解析json的,所以,我們需要把我們程式產生的字典轉化成json格式的json串(字串),然後網路傳輸,那邊接收到了之後,它愛怎麼處理是它的事情. 那如何把字典轉化成我們的json格式的字串呢?很簡單, 上程式碼:

import json
dic = {'a':'女王','b':'蘿莉','c':'小清新'}
s = json.dumps(dic) #把字典轉化成json字串
print(s)    #{"a": "\u5973\u738b", "b": "\u841d\u8389", "c": "\u5c0f\u6e05\u65b0"}

  結果不友好啊,那如何處理中文呢?在dumps的時候給出另一個引數ensure_ascii = False就可以了

import json
dic = {'a':'女王','b':'蘿莉','c':'小清新'}
s = json.dumps(dic,ensure_ascii = False) #把字典轉化成json字串
print(s)  #{"a": "女王", "b": "蘿莉", "c": "小清新"}

  搞定了,接下來,前端給你傳遞資訊了,你要把前端傳遞過來的json字串轉化成字典

import json

s = '{'a':'女王','b':'蘿莉','c':'小清新'}'
dic = json.loads(s)
print(type(dic),dic)

  搞定,是不是很簡單,以上兩個程式碼要求記住,理解,背會

  json也可以像pickle一樣把序列化的結果寫入到檔案中

dic = {'a':'女王','b':'蘿莉','c':'小清新'}
f = open('test.json',mode = 'w',encoding = 'utf-8')
json.dump(dic,f,ensure_ascii = False)  #把物件打散成json寫入到檔案中
f.close()

  同樣也可以從檔案中讀取一個json

f = open('test.json',mode = 'r',encoding = 'utf-8')
dic = json.load(f)
f.close()
print(dic)

  注意,我們可以向同一個檔案中寫入多個json串,但是讀不行

import json

lst = [{'a':1},{'b':2},{'c':3}]

f = open('test.json',mode = 'w',encoding = 'utf-8')

for el in lst:
    json.dump(el,f)
f.close()

  注意,此時檔案中的內容是一行內容

{"a": 1}{"b": 2}{"c": 3}

  這在讀取的時候是無法正常讀取的,那如何解決呢?兩套方案,方案一:把所有的內容準備好統一進行寫入和讀取,但是這樣處理如果資料小還好,資料量大的話就不夠友好了,方案二:不用dump,改用dumps和loads,對每一行分別進行處理

import json

lst = [{'a':1},{'b':2},{'c':3}]

#寫入
f = open('test.json',mode = 'w',encoding = 'utf-8')
for el in lst:
    s = json.dumps(el,ensure_ascii = True) + '\n'
    f.write(s)
f.close()

#讀取
f = open('test.json',mode = 'r',encoding = 'utf-8')
for line in f:
    dic = json.loads(line.strip())
    print(dic)
f.close()