<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你知道 Python 其實(shí)自帶了小型數(shù)據(jù)庫嗎

          共 7077字,需瀏覽 15分鐘

           ·

          2023-10-27 01:27

          Python客棧設(shè)為“星標(biāo)?
          第一時(shí)間收到最新資訊



          dbm



          DBM(DataBase Manager)是一種文件系統(tǒng),專門用于鍵值對(duì)的存儲(chǔ),最初是在 Unix 平臺(tái)實(shí)現(xiàn),現(xiàn)在其它平臺(tái)也可以用。對(duì)于 KV 模型,DBM 提供了一個(gè)輕量級(jí)、高效的存儲(chǔ)解決方案。

          總的來說,DBM 具有如下特點(diǎn):

          • 簡(jiǎn)單快速:非常簡(jiǎn)單易用,讀取和寫入操作都很快,適合存儲(chǔ)少量數(shù)據(jù)。

          • 鍵值對(duì)存儲(chǔ):數(shù)據(jù)是以鍵值對(duì)形式存儲(chǔ)的,你可以像操作 Python 字典一樣。

          • 文件存儲(chǔ):數(shù)據(jù)存在具體的文件中,可以輕松地備份和轉(zhuǎn)移。

          • 不支持復(fù)雜查詢:如果需要執(zhí)行復(fù)雜查詢或需要關(guān)系型數(shù)據(jù)庫的功能,DBM 可能不是一個(gè)好選擇。


           Python 標(biāo)準(zhǔn)庫提供了一個(gè) dbm 模塊,它實(shí)現(xiàn)了 DBM 文件系統(tǒng)的功,來看一下它的用法。

          import dbm

          # 第一個(gè)參數(shù)是文件名
          # 第二個(gè)參數(shù)是模式,有以下幾種
          #     r:只讀,要求文件必須存在,默認(rèn)就是這個(gè)模式
          #     w:可讀可寫,要求文件必須存在
          #     c:可讀可寫,文件不存在會(huì)創(chuàng)建,存在則追加
          #     n:可讀可寫,文件不存在會(huì)創(chuàng)建,存在則清空
          # 第三個(gè)參數(shù)是權(quán)限,用八進(jìn)制數(shù)字表示,默認(rèn) 0o666,即可讀可寫不可執(zhí)行
          db = dbm.open("store""c")

          # 打開文件就可以存儲(chǔ)值了,key 和 value 必須是字符串或 bytes 對(duì)象
          db["name"] = "S せんせい"
          db["age"] = "18"
          db[b"corporation"] = "小摩".encode("utf-8")

          # 關(guān)閉文件,將內(nèi)容寫到磁盤上
          db.close()

          非常簡(jiǎn)單,就像操作字典一樣,并且 key 是唯一的,如果存在則替換。執(zhí)行完后,當(dāng)前目錄會(huì)多出一個(gè) store.db 文件。

          我們打開它,然后讀取剛才寫入的鍵值對(duì)。

          import dbm

          db = dbm.open("store""c")

          # 獲取所有的 key,直接返回一個(gè)列表
          print(db.keys())
          """
          [b'corporation', b'name', b'age']
          """

          # 判斷一個(gè) key 是否存在,key 可以是字符串或 bytes 對(duì)象
          print("name" in db, "NAME" in db)
          """
          True False
          """

          # 獲取一個(gè) key 對(duì)應(yīng)的 value,得到的是 bytes 對(duì)象
          print(db["name"].decode("utf-8"))
          print(db[b"corporation"].decode("utf-8"))
          """
          S せんせい
          小摩
          """

          # key 如果不存在,會(huì)拋出 KeyError,我們可以使用 get 方法
          print(db.get("NAME"b"unknown"))
          """
          b'unknown'
          """

          # 當(dāng)然也可以使用 setdefault 方法,key 不存在時(shí),自動(dòng)寫進(jìn)去
          print(db.setdefault("gender"b"female"))
          """
          b'female'
          """

          print(db["gender"])
          """
          b'female'
          """

          非常簡(jiǎn)單,當(dāng)你需要存儲(chǔ)的數(shù)據(jù)量不適合放在內(nèi)存中,但又沒必要引入數(shù)據(jù)庫,那么不妨試試使用 dbm 模塊吧。

          當(dāng)然啦,dbm 雖然很方便,但它只能持久化 bytes 對(duì)象,字符串也是轉(zhuǎn)成 bytes 對(duì)象之后再存儲(chǔ)的。所以除了 dbm 之外,還有一個(gè)標(biāo)準(zhǔn)庫模塊 shelve,它可以持久化任意對(duì)象。



          shelve


          shelve 的使用方式和 dbm 幾乎是一致的,區(qū)別就是 shelve 的序列化能力要更強(qiáng),當(dāng)然速度自然也就慢一些。

          import shelve

          # 第二個(gè)參數(shù)表示模式,默認(rèn)是 c
          # 因此文件不存在會(huì)創(chuàng)建,存在則追加
          sh = shelve.open("shelve")

          sh["name"] = ["S 老師""高老師""電烤??架"]
          sh["age"] = {18}
          sh["job"] = {"tutu""大學(xué)生""xueer""醫(yī)生"}

          # 關(guān)閉文件,刷到磁盤中
          sh.close()

          執(zhí)行完之后,本地會(huì)多出一個(gè) shelve.db 文件,下面來讀取它。

          import shelve

          sh = shelve.open("shelve")

          print(sh["name"])
          print(sh["name"][2] == "電烤??架")
          """
          ['S 老師', '高老師', '電烤??架']
          True
          """

          print(sh["age"])
          """
          {18}
          """

          print(sh["job"])
          """
          {'tutu': '大學(xué)生', 'xueer': '醫(yī)生'}
          """


          sh.close()

          讀取出來的就是原始的對(duì)象,我們可以直接操作它。

          然后自定義類的實(shí)例對(duì)象也是可以的。

          import shelve

          class People:
              def __init__(self, name, age):
                  self.name = name
                  self.age = age

              @property
              def print_info(self):
                  return f"name is {self.name}, age is {self.age}"

          sh = shelve.open("shelve")

          p = People("群主"58)
          # 將類、和該類的實(shí)例對(duì)象存儲(chǔ)進(jìn)去
          sh["People"] = People
          sh["p"] = p
          sh.close()

          執(zhí)行完之后,我們打開它。

          import shelve

          sh = shelve.open("shelve")

          # 需要注意的是,People 是我們自己定義的類
          # 如果你想要將其還原出來,那么該類必須要出現(xiàn)在當(dāng)前的命名空間中
          try:
              sh["People"]
          except AttributeError as e:
              print(e)
              """
              Can't get attribute 'People' on <module ...>
              """


          class People:
              def __init__(self, name, age):
                  self.name = name
                  self.age = age

              @property
              def print_info(self):
                  return f"name is {self.name}, age is {self.age}"

          print(sh["People"is People)
          """
          True
          """

          print(sh["p"].print_info)
          """
          name is 群主, age is 58
          """

          print(sh["People"]("群主"38).print_info)
          """
          name is 群主, age is 38
          """

          這就是 shelve 模塊,非常強(qiáng)大,當(dāng)然它底層也是基于 pickle 實(shí)現(xiàn)的。如果你不需要存儲(chǔ)復(fù)雜的 Python 對(duì)象,只需要存儲(chǔ)字符串的話,那么還是推薦 dbm。

          然后在使用 shelve 的時(shí)候,需要注意里面的一個(gè)坑。

          import shelve

          # 打開文件,設(shè)置鍵值對(duì)
          sh = shelve.open("shelve")
          sh["name"] = "古明地覺"
          sh["score"] = [808080]
          sh.close()

          # 重新打開文件,修改鍵值對(duì)
          sh = shelve.open("shelve")
          sh["name"] = "芙蘭朵露"
          sh["score"].append(90)
          sh.close()

          # 再次重新打開文件,查看鍵值對(duì)
          sh = shelve.open("shelve")
          print(sh["name"])
          print(sh["score"])
          """
          芙蘭朵露
          [80, 80, 80]
          """

          sh.close()

          第一次打開文件創(chuàng)建兩個(gè)鍵值對(duì),第二次打開文件鍵值對(duì)修改,第三次打開文件查看鍵值對(duì)。但是我們發(fā)現(xiàn) sh["name"] 變了,而 sh["score"] 卻沒變,這是什么原因?

          當(dāng)我們修改 name 時(shí),采用的是直接賦值的方式,會(huì)將原本內(nèi)存里的值給替換掉。而修改 score 時(shí),是在原有值的基礎(chǔ)上做 append 操作,它的內(nèi)存地址并沒有變。

          所以可變對(duì)象在本地進(jìn)行修改,shelve 默認(rèn)是不會(huì)記錄的,除非創(chuàng)建新的對(duì)象,并把原有的對(duì)象給替換掉。所以 sh["score"].append(90) 之后,sh["score"] 仍是 [80, 80, 80]而不是 [80, 80, 80, 90]

          因?yàn)?shelve 沒有記錄對(duì)象自身的修改,如果想得到期望的結(jié)果,一種方法是把對(duì)象整體換掉。也就是讓 sh["score"] = [80, 80, 80, 90]這樣等于是創(chuàng)建了一個(gè)新的對(duì)象并重新賦值,是可行的。

          或者你在打開文件的時(shí)候,多指定一個(gè)參數(shù) writeback。

          import shelve

          # 打開文件,設(shè)置鍵值對(duì)
          sh = shelve.open("shelve")
          sh["name"] = "古明地覺"
          sh["score"] = [808080]
          sh.close()

          # 重新打開文件,修改鍵值對(duì)
          sh = shelve.open("shelve", writeback=True)
          sh["name"] = "芙蘭朵露"
          sh["score"].append(90)
          sh.close()

          # 再次重新打開文件,查看鍵值對(duì)
          sh = shelve.open("shelve")
          print(sh["name"])
          print(sh["score"])
          """
          芙蘭朵露
          [80, 80, 80, 90]
          """

          sh.close()

          可以看到都發(fā)生改變了,但這個(gè)參數(shù)會(huì)導(dǎo)致額外的內(nèi)存消耗。當(dāng)指定 writeback=True 的時(shí)候,shelve 會(huì)將讀取的對(duì)象都放到一個(gè)內(nèi)存緩存當(dāng)中。比如我們操作了 20 個(gè)持久化的對(duì)象,但只修改了一個(gè),剩余的 19 個(gè)只是查看并沒有做修改,但當(dāng) sh.close() 的時(shí)候,會(huì)將這 20 個(gè)對(duì)象都寫回去。

          因?yàn)?shelve 不知道你會(huì)對(duì)哪個(gè)對(duì)象做修改,所以不管你是查看還是修改,都會(huì)放到緩存當(dāng)中,然后再一次性都寫回去。這樣就會(huì)造成兩點(diǎn)影響:

          • shelve 會(huì)把我們使用的對(duì)象放到內(nèi)存的另一片空間中,等于是額外拷貝了一份。

          • 雖然操作了 N 個(gè)對(duì)象,但只修改了 1 個(gè),而 shelve 會(huì)把 N 個(gè)對(duì)象都重新寫回去,從而造成性能上的問題,導(dǎo)致效率降低。


          因此加不加這個(gè)參數(shù),由具體情況決定。

          綜上所述,Python 算是自帶了小型數(shù)據(jù)庫,看看能不能在合適的場(chǎng)景中把它用上。

          往期推薦

          1、一日一技:HTML里面提取的JSON怎么解析不了?

          2、用 Python 讀取照片的 Exif 信息

          3加密的手機(jī)號(hào),如何模糊查詢?

          4、我學(xué)習(xí)Python的三個(gè)神級(jí)網(wǎng)站

          5、自己擁有一臺(tái)服務(wù)器,可以做哪些很酷的事情?


             
             

          點(diǎn)擊關(guān)注公眾號(hào),閱讀更多精彩內(nèi)容

          瀏覽 1169
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情黄色婷婷 | 国产日韩一区二区三免费高清 | 人人妻人人操裸贷 | 第一色在线 | 蜜桃精品无码视频网站 |