19.Python之模塊

Python之模塊

  1. 模塊

    • Python模塊(Module),本質(zhì)就是一個(gè)Python文件秒裕,以 .py 結(jié)尾,包含了Python對(duì)象定義和Python語(yǔ)句钞啸,是封裝語(yǔ)句的最小單位几蜻。一個(gè)模塊就是就是包含了一組功能的Python文件,比如spam.py体斩,模塊名為spam梭稚,可以通過(guò) import spam 調(diào)用模塊。模塊不宜過(guò)大絮吵,不便于維護(hù)弧烤。

  1. 模塊的分類(lèi)

    在Python中,模塊的使用方法都是一樣的蹬敲,可以細(xì)分為四個(gè)通用類(lèi)別:

    • 使用Python編寫(xiě)的.py文件
    • 已被編譯為共享庫(kù)或DLL的C或C++擴(kuò)展
    • 把一系列模塊組織到一起的文件夾(注:該文件夾下有一個(gè) __init__.py 文件暇昂,該文件夾稱(chēng)之為包,導(dǎo)入一個(gè)包相當(dāng)于執(zhí)行了這個(gè)包下的__init__.py文件粱栖,并不是把這個(gè)包下的所有文件都導(dǎo)入進(jìn)來(lái))
    • 使用C語(yǔ)言編寫(xiě)话浇,并鏈接到Python解釋器的內(nèi)置模塊

  1. 使用模塊的意義

    • 模塊讓你能夠有邏輯地組織你的 Python 代碼段;把相關(guān)的代碼分配到一個(gè)模塊里能讓你的代碼更好用闹究,更易懂幔崖;模塊能定義函數(shù),類(lèi)和變量渣淤,模塊里也能包含可執(zhí)行的代碼赏寇;拿來(lái)主義,提升開(kāi)發(fā)效率价认。

  1. 自定義模塊

    • 本質(zhì)就是創(chuàng)建一個(gè)Python文件嗅定。自定義模塊開(kāi)頭應(yīng)注釋說(shuō)明自定義模塊的作用,以下是time模塊的注釋說(shuō)明

      # encoding: utf-8
      # module time
      # from (built-in)
      # by generator 1.147
      """
      This module provides various functions to manipulate time values.
      
      There are two standard representations of time.  One is the number
      of seconds since the Epoch, in UTC (a.k.a. GMT).  It may be an integer
      or a floating point number (to represent fractions of seconds).
      The Epoch is system-defined; on Unix, it is generally January 1st, 1970.
      The actual value can be retrieved by calling gmtime(0).
      
      The other representation is a tuple of 9 integers giving local time.
      The tuple items are:
        year (including century, e.g. 1998)
        month (1-12)
        day (1-31)
        hours (0-23)
        minutes (0-59)
        seconds (0-59)
        weekday (0-6, Monday is 0)
        Julian day (day in the year, 1-366)
        DST (Daylight Savings Time) flag (-1, 0 or 1)
      If the DST flag is 0, the time is given in the regular time zone;
      if it is 1, the time is given in the DST time zone;
      if it is -1, mktime() should guess based on the date and time.
      """
      # no imports
      
      # Variables with simple values
      
    • 自定義模塊中出現(xiàn)的變量用踩、可執(zhí)行語(yǔ)句渠退、函數(shù)定義等稱(chēng)之為模塊的成員。


  1. 模塊的運(yùn)行方式

    • 腳本方式:直接使用解釋器執(zhí)行脐彩,或PyCharm等軟件中直接運(yùn)行

    • 模塊方式:被其他模塊導(dǎo)入執(zhí)行碎乃,為導(dǎo)入它的模塊提供資源(變量、函數(shù)定義和類(lèi)定義等)惠奸。當(dāng)自定義模塊被其它模塊導(dǎo)入時(shí)梅誓,其中的可執(zhí)行語(yǔ)句會(huì)立即執(zhí)行。在Python中, __name__ 是屬于 python 中的內(nèi)置類(lèi)屬性梗掰,代表對(duì)應(yīng)程序名稱(chēng)嵌言。當(dāng)模塊以腳本方式運(yùn)行時(shí),__name__等于__main__及穗,當(dāng)模塊以導(dǎo)入方式運(yùn)行時(shí)摧茴,__name__等于模塊的名字。通過(guò)這一特性可以解決模塊被導(dǎo)入方式運(yùn)行時(shí)埂陆,可執(zhí)行語(yǔ)句會(huì)立即執(zhí)行的問(wèn)題蓬蝶。

      # 在自定義模塊中,通巢峦铮可執(zhí)行程序放在下面這條判斷語(yǔ)句之下丸氛,而成員定義放在這條判斷語(yǔ)句之上。
      user = 'Python'
      
      def func_1():
          pass
      
      def func_2():
          pass
      
      # 通常會(huì)將所有可執(zhí)行的語(yǔ)句放在一個(gè)測(cè)試函數(shù)內(nèi)著摔,在開(kāi)發(fā)階段調(diào)用這個(gè)函數(shù)執(zhí)行本模塊功能測(cè)試
      def main():
          func_1()
          func_2()
          
      if __name__ == '__main__':  # 在Pycharm中輸入main按回車(chē)可以快速生成
          main()
      

  1. 系統(tǒng)導(dǎo)入模塊的路徑

    • 內(nèi)存中:如果成功導(dǎo)入過(guò)模塊缓窜,直接使用已經(jīng)存在的模塊。

    • 內(nèi)置路徑中:Python解釋器安裝路徑下的Lib文件夾谍咆。

    • sys.path:是一個(gè)路徑列表禾锤,可以動(dòng)態(tài)修改。

      import sys
      print(sys.path)
      
      # 如果自定義模塊與調(diào)用模塊不在同一路徑下摹察,需要將自定義模塊的路徑添加到sys.path中
      # 將路徑添加到sys.path中
      sys.path.append(r'自定義模塊的絕對(duì)路徑')
      # 使用os模塊獲取一個(gè)路徑的父路徑
      import os
      os.path.dirname(__file__) + r'自定義模塊所在的文件夾'  # __file__ 獲取當(dāng)前文件的絕對(duì)路徑
      # 因此恩掷,將一個(gè)模塊的路徑添加到sys.path中可以這樣寫(xiě)
      

    sys.path.append(os.path.dirname(file + '自定義模塊所在的文件夾'))
    ```


  1. 模塊的導(dǎo)入方式

    • 方式1:導(dǎo)入模塊的所有成員,調(diào)用成員時(shí)必須使用模塊名稱(chēng).成員名稱(chēng)的方式

      import 模塊名稱(chēng)
      
      • 首次導(dǎo)入模塊發(fā)生的三件事:
        • 創(chuàng)建一個(gè)模塊的名稱(chēng)空間供嚎;
        • 執(zhí)行模塊對(duì)應(yīng)文件黄娘,將產(chǎn)生的名字存放于創(chuàng)建的名稱(chēng)空間中;
        • 在當(dāng)前執(zhí)行文件中拿到一個(gè)模塊名克滴,該模塊名指向創(chuàng)建的名稱(chēng)空間逼争。
      • 注意:多次調(diào)用模塊只會(huì)引用第一次調(diào)用時(shí)導(dǎo)入的結(jié)果,不會(huì)重復(fù)執(zhí)行模塊;且實(shí)行模塊中的功能,始終以模塊的名稱(chēng)空間為準(zhǔn)召锈。
    • 方式2:一次性導(dǎo)入多個(gè)模塊的成員

      import 模塊名稱(chēng)1,模塊名稱(chēng)2,模塊名稱(chēng)3,…… # 不建議這么寫(xiě),最好分開(kāi)寫(xiě)
      
    • 方式3:從一個(gè)模塊中導(dǎo)入某個(gè)成員

      from 模塊名稱(chēng) import 成員名稱(chēng)   # 好處是節(jié)省內(nèi)存空間
      
      • 首次導(dǎo)入模塊發(fā)生的三件事:
      • 創(chuàng)建一個(gè)模塊的名稱(chēng)空間杂伟;
        • 執(zhí)行模塊對(duì)應(yīng)文件,將產(chǎn)生的名字存放于創(chuàng)建的名稱(chēng)空間中仍翰;
        • 在當(dāng)前名稱(chēng)空間中直接拿到模塊中的名字赫粥,可以直接使用,不用加任何模塊名前綴歉备。
      • 注意:多次調(diào)用模塊只會(huì)引用第一次調(diào)用時(shí)導(dǎo)入的結(jié)果傅是,不會(huì)重復(fù)執(zhí)行模塊匪燕;且實(shí)行模塊中的功能蕾羊,始終以模塊的名稱(chēng)空間為準(zhǔn)喧笔。此方式有可能與當(dāng)前名稱(chēng)空間的名字沖突。
      • 區(qū)別:
        • import 模塊名 的方式調(diào)用模塊時(shí),需要以模塊名.模塊中功能或方法的名字使用龟再。
        • from 模塊名 import 模塊中功能的名字的方式調(diào)用模塊時(shí),直接用模塊中功能或方法的名字使用书闸。
    • 方式4:從一個(gè)模塊中導(dǎo)入多個(gè)個(gè)成員

      from 模塊名稱(chēng) import 成員名稱(chēng)1,成員名稱(chēng)2,成員名稱(chēng)3
      
    • 方式5:從一個(gè)模塊中導(dǎo)入所有成員,調(diào)用時(shí)直接使用成員名稱(chēng)利凑,但容易導(dǎo)致命名沖突

      from 模塊名稱(chēng) import *
      
    • 方式6:使用別名alias(縮寫(xiě)為:as)避免命名沖突

      # 為模塊起別名
      import 模塊名稱(chēng)1 as 模塊名稱(chēng)2
      # 為成員起別名
      from 模塊名稱(chēng) import 成員名稱(chēng)1 as 成員名稱(chēng)2
      
    • 方式7:控制from 模塊名稱(chēng) import *成員的導(dǎo)入

      __all__是一個(gè)列表浆劲,用于表示本模塊可以被外界使用的成員。元素是成員名字的字符串哀澈。此方式只針對(duì)from 模塊名稱(chēng) import *的導(dǎo)入方式生效牌借。

      __all__ = ['a', 'b', 'c']
      
      a = 1
      b = 2
      c = 3
      # 成員d不會(huì)被導(dǎo)入
      d = 4
      
    • 方式8:相對(duì)導(dǎo)入。針對(duì)一個(gè)項(xiàng)目中的不同模塊間的導(dǎo)入(可以在不同的文件夾下)割按,稱(chēng)之為相對(duì)導(dǎo)入膨报。主要用于隱藏同項(xiàng)目中導(dǎo)入的其他模塊。

      '''
      文件結(jié)構(gòu):
      d
          d_1
              d_1_f.py
          d_2
              d_2_f1.py
              d_2_f2.py
              
      '''
      # 如果d_2_f1.py需要相對(duì)導(dǎo)入d_2_f2.py
      from . import d_2_f2.py
      # 如果d_1_f.py作為項(xiàng)目入口适荣,需要調(diào)用d_2_f1.py
      # .表示相對(duì)路徑
      # ..表示父路徑
      # ...表示父路徑的父路徑
      from .. d_2.d_2_f1 import *
      
      

  1. 常用模塊

    • random模塊:提供了獲取偽隨機(jī)數(shù)相關(guān)的方法

      • random.random():獲取一個(gè)[0,1)范圍內(nèi)的隨機(jī)浮點(diǎn)數(shù)现柠。

      • random.randint(a, b):獲取一個(gè)[a, b]范圍內(nèi)的隨機(jī)整數(shù)。

      • random.uniform(a, b):獲取一個(gè)[a, b]范圍內(nèi)的隨機(jī)浮點(diǎn)數(shù)弛矛。

      • random.shuffle(x):將x中的元素順序隨機(jī)打亂够吩,參數(shù)x必須是一個(gè)可變數(shù)據(jù)類(lèi)型。

      • random.sample(x, k):從x中隨機(jī)抽取k個(gè)數(shù)據(jù)丈氓,組成一個(gè)列表返回周循。


    • time模塊:提供了獲取時(shí)間戳相關(guān)的方法

      • time.time():獲取當(dāng)前的時(shí)間戳(從計(jì)算機(jī)元年1970年1月1日0點(diǎn)0分0秒到現(xiàn)在經(jīng)過(guò)的秒數(shù))。

      • time.gmtime():獲取GMT格式化時(shí)間對(duì)象万俗,默認(rèn)參數(shù)為當(dāng)前時(shí)間戳鱼鼓。

      • time.localtime():獲取本地格式化時(shí)間對(duì)象,默認(rèn)參數(shù)為當(dāng)前時(shí)間戳该编。

      • time.mktime()格式化時(shí)間對(duì)象轉(zhuǎn)換成時(shí)間戳迄本。

        import time
        print(time.mktime(time.localtime()))
        
      • time.strftime():格式化時(shí)間對(duì)象轉(zhuǎn)換成字符串,默認(rèn)參數(shù)為當(dāng)前時(shí)間戳课竣。

        import time
        print(time.strftime('%Y-%m-%d %H:%M:%S'))   # 2020-02-18 22:18:58
        
      • time.strptime():字符串轉(zhuǎn)換成格式化時(shí)間對(duì)象嘉赎。

        import time
        print(time.strptime('2020-02-18 22:18:58','%Y-%m-%d %H:%M:%S'))
        # 輸出結(jié)果:time.struct_time(tm_year=2020, tm_mon=2, tm_mday=18, tm_hour=22, tm_min=18, tm_sec=58, tm_wday=1, tm_yday=49, tm_isdst=-1)
        
      • time.sleep(secs):暫停當(dāng)前線程,睡眠secs


    • datetime 模塊:日期時(shí)間模塊于樟。封裝了和日期公条、時(shí)間相關(guān)的類(lèi),主要用于數(shù)學(xué)計(jì)算迂曲。

      • datetime中的date類(lèi):格式化輸出:年-月-日

        import datetime
        d = datetime.date(2020,1,1)
        print(d)    # 2020-01-01
        print(d.year)   # 獲取date對(duì)象的year屬性:2010
        print(d.month)  # 獲取date對(duì)象的month屬性:1
        print(d.day)    # # 獲取date對(duì)象的day屬性:1
        
      • datetime中的time類(lèi):格式化輸出:時(shí):分:秒

        import datetime
        t = datetime.time(10,59,59)
        print(t)    # 10:59:59
        print(t.hour)   # 獲取time對(duì)象的hour屬性:10
        print(t.minute) # 獲取time對(duì)象的miute屬性:59
        print(t.second) # 獲取time對(duì)象的second屬性:59
        
      • datetime中的datetime類(lèi):格式化輸出:年-月-日 時(shí):分:秒

        import datetime
        dt = datetime.datetime(2020,1,1,10,59,59)
        print(dt)
        print(dt.year)
        print(dt.month)
        print(dt.day)
        print(dt.hour)
        print(dt.minute)
        print(dt.second)
        
      • datetime中的timedelta類(lèi):輸出時(shí)間的變化量靶橱,用于時(shí)間的運(yùn)算,運(yùn)算的結(jié)果類(lèi)型和操作數(shù)保持一致。

        import datetime
        dt = datetime.timedelta(days=1)
        print(dt)   # 1 day, 0:00:00
        d = datetime.date(2020,1,1)
        res = d + dt
        print(res)  # 2020-01-02
        
        # 根據(jù)用戶輸入的年份判斷是否是閏年关霸,閏年2月有29天传黄,平年2月有28天
        # 計(jì)算方法:使用datetime模塊,首先創(chuàng)建指定的年份的3月1日队寇,往前走一天
        import datetime
        while 1:
            year = input('請(qǐng)輸入年份:').strip()
            year = int(year)    # 將用戶輸入的字符串類(lèi)型轉(zhuǎn)換成整數(shù)類(lèi)型
            d = datetime.date(year,3,1)
            td = datetime.timedelta(days=1)
            res = d - td
            if res.day == 29:
                print(f'{year}年是閏年膘掰!')
            else:
                print(f'{year}年是平年。')
        

        注意:只有date佳遣、datetime识埋、timedelta類(lèi)才能與timedelta類(lèi)之間可以進(jìn)行運(yùn)算,并且會(huì)產(chǎn)生進(jìn)位零渐;而time類(lèi)不能與timedelta類(lèi)進(jìn)行運(yùn)算窒舟。


    • os 模塊:提供了文件操作的常用方法。(自動(dòng)化運(yùn)維常用的模塊為shutil

      • os.remove():刪除文件
      • os.rename():修改文件名稱(chēng)
      • os.removedirs():刪除空目錄诵盼,只能刪除空目錄辜纲。
      • os.path:path模塊是os模塊的子模塊,封裝了很多文件路徑的操作方法拦耐。
      • os.system('command'):執(zhí)行系統(tǒng)的command命令

    • sys 模塊:提供了和Python解釋器相關(guān)的操作耕腾。

      • sys.argv:在程序中獲取Python文件通過(guò)命令行運(yùn)行后時(shí)后面的參數(shù),sys.argv[0]獲取的是文件名杀糯,sys.argv[1]獲取文件名后的第一個(gè)參數(shù)扫俺,sys.argv[2]獲取文件名后的第二個(gè)參數(shù)。
      • sys.path:以列表的形式返回解釋器尋找模塊的路徑固翰。
      • sys.modules:以字典的形式返回系統(tǒng)已經(jīng)加載的模塊狼纬。

    • json 模塊:將數(shù)據(jù)轉(zhuǎn)換成字符串,用于數(shù)據(jù)存儲(chǔ)和傳輸骂际。結(jié)構(gòu)化數(shù)據(jù)不能直接寫(xiě)入文件疗琉,只有非結(jié)構(gòu)化的線性數(shù)據(jù)才可以。json已經(jīng)成為一種簡(jiǎn)單通用的數(shù)據(jù)交換格式(可以跨語(yǔ)言數(shù)據(jù)交互)歉铝。

      • 序列化 (Serialization):將內(nèi)存中的數(shù)據(jù)盈简,轉(zhuǎn)換成字節(jié),用以保存在文件或通過(guò)網(wǎng)絡(luò)傳輸太示,稱(chēng)之為序列化過(guò)程(把數(shù)據(jù)從內(nèi)存中拿出去)柠贤。可json序列化的數(shù)據(jù)類(lèi)型有數(shù)值类缤、字符串臼勉、列表、元組餐弱、字典等宴霸,但集合不可被json序列化囱晴,同時(shí),元組被序列化后瓢谢,會(huì)變成列表形式的字符串畸写。

        • json.dump(obj, f):將指定的對(duì)象存儲(chǔ)到文件中,從內(nèi)存到硬盤(pán)恩闻。

          import json
          with open(r'test.txt', mode='wt', encoding='UTF-8') as f:   # 注意:以text類(lèi)型寫(xiě)入
              json.dump([1,2,3,4,5],f)
          
        • json.dumps(obj):將指定的對(duì)象轉(zhuǎn)換成json格式的字符串,從內(nèi)存到內(nèi)存剧董。

          import json
          res = json.dumps([1,2,3])
          print(res,type(res))    # [1, 2, 3] <class 'str'>
          
          # json文件通常是一次性寫(xiě)幢尚,但通過(guò)多次序列化的方式可以實(shí)現(xiàn)多次寫(xiě)
          import json
          with open(r'test.txt', mode='at', encoding='UTF-8') as f:
              f.write(json.dumps([1, 2, 3]) + '\n')
              f.write(json.dumps([4, 5, 6]) + '\n')
          
      • 反序列化 (Deserialization):從文件、網(wǎng)絡(luò)中獲取的數(shù)據(jù)轉(zhuǎn)換成內(nèi)存中原來(lái)的數(shù)據(jù)類(lèi)型翅楼,稱(chēng)之為反序列化過(guò)程尉剩。(把數(shù)據(jù)拿到內(nèi)存中)

        • json.load(f):將文件中的字符串?dāng)?shù)據(jù)轉(zhuǎn)換成序列化前的數(shù)據(jù)類(lèi)型。

          import json
          with open(r'test.txt', mode='rt', encoding='UTF-8') as f:
              b = json.load(f)
              print(b,type(b))    # [1, 2, 3, 4, 5] <class 'list'>
          
        • json.loads(s):將內(nèi)存中的字符串?dāng)?shù)據(jù)轉(zhuǎn)換成序列化前的數(shù)據(jù)類(lèi)型毅臊。

          import json
          res = json.dumps([1,2,3])
          l = json.loads(res)
          print(l,type(l))    # [1, 2, 3] <class 'list'>
          
          # json文件通常是一次性讀理茎,但通過(guò)多次反序列化的方式i可以實(shí)現(xiàn)多次讀
          import json
          with open(r'test.txt', mode='rt', encoding='UTF-8') as f:
              for i in f:
                  res = json.loads(i.strip('\n'))
          

    • pickle 模塊:可以將Python中所有的數(shù)據(jù)類(lèi)型進(jìn)行序列化與反序列化的過(guò)程,將數(shù)據(jù)類(lèi)型與字節(jié)相互轉(zhuǎn)換管嬉≡砹郑可以多次對(duì)同一個(gè)文件進(jìn)行序列化,但pickle序列化的數(shù)據(jù)只能用于Python蚯撩!

      • 序列化:相較于json模塊础倍,pickle 模塊序列化的更徹底,直接將數(shù)據(jù)類(lèi)型轉(zhuǎn)換成的是字節(jié)胎挎,而不是字符串沟启。

        • pickle.dump:把pickle序列化內(nèi)容從內(nèi)存寫(xiě)入到硬盤(pán)文件。

          import pickle
          with open(r'test.txt', mode='wb') as f:    # 注意:以bytes類(lèi)型寫(xiě)入 
              pickle.dump([1,2,3],f)
          
        • pickle.dumps:把pickle序列化內(nèi)容從內(nèi)存寫(xiě)入到內(nèi)存犹菇。

          import pickle
          res = pickle.dumps(10)
          print(res,type(res))    # b'\x80\x04K\n.' <class 'bytes'>
          
      • 反序列化:將字節(jié)文件轉(zhuǎn)換成序列化前的數(shù)據(jù)類(lèi)型德迹。

        • pickle.load:將硬盤(pán)文件中的字節(jié)寫(xiě)到內(nèi)存中,并轉(zhuǎn)換成序列化前的數(shù)據(jù)類(lèi)型

          import pickle
          with open(r'test.txt', mode='rb') as f:
              res = pickle.load(f)
              print(res,type(res))    # [1, 2, 3] <class 'list'>
          
        • pickle.loads:將內(nèi)存中的字節(jié)寫(xiě)到內(nèi)存中揭芍,并轉(zhuǎn)換成序列化前的數(shù)據(jù)類(lèi)型

          import pickle
          res = pickle.dumps(10)
          l = pickle.loads(res)
          print(l,type(l))    # 10 <class 'int'>
          

    • hashlib 模塊:封裝一些用于加密的類(lèi)胳搞。加密的目的是用來(lái)驗(yàn)證文件,而非解密文件称杨。

      • 特點(diǎn):

        • 將一個(gè)數(shù)據(jù)切片后流酬,對(duì)每片數(shù)據(jù)進(jìn)行加密,所有數(shù)據(jù)片組裝后的加密結(jié)果與直接對(duì)文件加密的結(jié)果一致列另;
        • 單向加密不可逆芽腾;
        • 原始數(shù)據(jù)的微小變化,將導(dǎo)致加密結(jié)果的雪崩式差異页衙;
        • 無(wú)論文件多大摊滔,hash值的長(zhǎng)度是固定的阴绢。不同加密算法,加密結(jié)果的長(zhǎng)度不同艰躺;
        • 只能對(duì)字節(jié)進(jìn)行加密呻袭。
      • 使用:

        • 生成一個(gè)文件的hash值

          import hashlib
          # 獲取一個(gè)加密對(duì)象
          user_file = hashlib.md5()
          user_file_path = input('請(qǐng)輸入您需要驗(yàn)證程序或文件的路徑:'.strip())
          with open(f'{user_file_path}', mode='rb') as f:    # 以binary(二進(jìn)制)方式讀
              for line in f:
                  # 使用加密對(duì)象的update方法,把值傳給md5算法進(jìn)行加密
                  user_file.update(line)
              # 通過(guò)hexdigest()方法獲取加密結(jié)果,返回一個(gè)十六進(jìn)制的字符串
              hash_value = user_file.hexdigest()
          print(f'您程序或文件的hash值為:{hash_value}')
          
          # 注意:以下寫(xiě)法的值是一樣的
          # 寫(xiě)法1
          import hashlib
          m = hashlib.md5(b'abc')
          print(m.hexdigest())    # 900150983cd24fb0d6963f7d28e17f72
          # 寫(xiě)法2
          m = hashlib.md5()
          m.update(b'abc')
          print(m.hexdigest())    # 900150983cd24fb0d6963f7d28e17f72
          
        • 驗(yàn)證兩個(gè)文件的hash值是否相同腺兴,判斷兩個(gè)文件的原文是否相同左电。

        • 加鹽:為了防止黑客通過(guò)彩虹表根據(jù)哈希值反推原始口令,在計(jì)算哈希的時(shí)候页响,不能僅針對(duì)原始輸入計(jì)算篓足,需要增加一個(gè)salt來(lái)使得相同的輸入也能得到不同的哈希,這樣闰蚕,大大增加了黑客破解的難度栈拖。如果salt是我們自己隨機(jī)生成的,通常我們計(jì)算MD5時(shí)采用md5(message + salt)没陡。但實(shí)際上涩哟,把salt看做一個(gè)“口令”,加salt的哈希就是:計(jì)算一段message的哈希時(shí)盼玄,根據(jù)不通口令計(jì)算出不同的哈希贴彼。要驗(yàn)證哈希值,必須同時(shí)提供正確的口令埃儿。

          import hashlib
          # 獲取一個(gè)加密對(duì)象
          user_file = hashlib.md5(b'salt')    # 加鹽
          user_file_path = input('請(qǐng)輸入您需要驗(yàn)證程序或文件的路徑:'.strip())
          with open(f'{user_file_path}', mode='rb') as f:    # 以binary(二進(jìn)制)方式讀
              for line in f:
                  # 使用加密對(duì)象的update方法锻弓,把值傳給md5算法進(jìn)行加密
                  user_file.update(line)
              # 通過(guò)hexdigest()方法獲取加密結(jié)果,返回一個(gè)十六進(jìn)制的字符串
              hash_value = user_file.hexdigest()
          print(f'您程序或文件的hash值為:{hash_value}') #4795d80f956d95feab5f1dedc7b51792
          

    • hmac 模塊:Keyed-Hashing for Message Authentication 它通過(guò)一個(gè)標(biāo)準(zhǔn)算法,在計(jì)算哈希的過(guò)程中蝌箍,把key混入計(jì)算過(guò)程中青灼。

      • hashlib加salt算法不同,hmac算法針對(duì)所有哈希算法都通用妓盲,無(wú)論是MD5還是SHA-1杂拨。采用hmac替代我們自己的salt算法,可以使程序算法更標(biāo)準(zhǔn)化悯衬,也更安全弹沽。Python自帶的hmac模塊實(shí)現(xiàn)了標(biāo)準(zhǔn)的hmac算法。我們來(lái)看看如何使用hmac實(shí)現(xiàn)帶key的哈希筋粗。

        import hmac
        message = b'Hello, world!'
        key = b'secret'
        h = hmac.new(key, message, digestmod='MD5')
        # 如果消息很長(zhǎng)策橘,可以多次調(diào)用h.update(msg)
        h.hexdigest()
        

    • subprocess 模塊:Python 2.4 中新增的一個(gè)模塊,它允許你生成新的進(jìn)程娜亿,連接到它們的 input/output/error 管道丽已,并獲取它們的返回(狀態(tài))碼。這個(gè)模塊的目的在于替換幾個(gè)舊的模塊和方法买决,如:os.system沛婴,os.spawn

      import subprocess
      
      obj=subprocess.Popen('yum -y update',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
      # shell=True 表示使用解釋器解釋命令吼畏;
      # stdout=subprocess.PIPE 表示將正確的結(jié)果往stdout管道丟;
      # stderr=subprocess.PIPE 表示將錯(cuò)誤的結(jié)果往stderr管道丟嘁灯;
      # PIPE就是管道的意思
      
      res_stdout=obj.stdout.read() # 通過(guò)管道讀取正確的結(jié)果泻蚊,而且,結(jié)果只能取一次丑婿,取走了就沒(méi)有了
      print(res_stdout.decode('utf-8'))
      
      res_stderr=obj.stderr.read() # 通過(guò)管道讀取錯(cuò)誤的結(jié)果性雄,而且,結(jié)果只能取一次羹奉,取走了就沒(méi)有了
      print(res_stderr.decode('utf-8'))
      

    • configparser 模塊:該基本配置語(yǔ)言提供的結(jié)構(gòu)類(lèi)似于Microsoft Windows INI文件中的結(jié)構(gòu)秒旋。用于生成和修改常見(jiàn)配置文檔。


    • shutil 模塊:高級(jí)的文件尘奏、文件夾滩褥、壓縮包處理模塊病蛉。

      • 拷貝文件:

        import shutil
        shutil.copy2('src', 'dst')
        
      • 拷貝目錄:

        import shutil
        shutil.copytree('src', 'dst', ignore=shutil.ignore_patterns('*.mp4'))
        # ignore=shutil.ignore_patterns('*.mp4')可以指定哪些文件不拷貝炫加,根據(jù)自己需求,可以不用寫(xiě)
        
      • 刪除目錄:

        import shutil
        shutil.rmtree('src', ignore_errors=True)
        
      • 移動(dòng)文件或目錄:

        import shutil
        shutil.move('src', 'dst', copy_function=shutil.copy2)
        
      • 獲取磁盤(pán)使用空間:

        import shutil
        total, used, free = shutil.disk_usage(r'c:/')
        print(F'總大衅倘弧:{total/1024/1024/1024}GB俗孝,可使用大小:{used/1024/1024/1024}GB魄健,剩余大懈陈痢:{free/1024/1024/1024}GB')
        
      • 壓縮文件:

        import shutil
        shutil.make_archive('test.txt', 'zip', 'root_dir')
        
      • 解壓文件:

        import shutil
        shutil.unpack_archive('filename', 'extract_dir')
        

    • logging 模塊:日志模塊,一般用來(lái)trouble shooting和數(shù)據(jù)分析沽瘦。但無(wú)論希望日志里打印哪些內(nèi)容革骨,都得自己寫(xiě),沒(méi)有自動(dòng)生成日志這種事兒析恋。

      • 導(dǎo)入日志模塊

        import logging
        logging.debug('debug message')
        logging.info('info message')
        logging.warning('warning message')
        logging.error('error message')
        logging.critical('critical message')
        
      • 定義日志基本配置

        import logging
        
        logging.basicConfig(
            format='%(asctime)s - %(filename)s - [line:%(lineno)d] - %(levelname)s: %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S',
            filename='parser_result.log',
            filemode='a'
        )
        
        logging.debug('debug message')
        logging.info('info message')
        logging.warning('warning message')
        logging.error('error message')
        logging.critical('critical message')
        
      • logging.basicConfig函數(shù)各參數(shù):

        • filename: 指定日志文件名
        • filemode: 和file函數(shù)意義相同良哲,指定日志文件的打開(kāi)模式,'w'或'a'
        • format: 指定輸出的格式和內(nèi)容助隧,format可以輸出很多有用信息筑凫,如上例所示:
          • %(levelno)s: 打印日志級(jí)別的數(shù)值
          • %(levelname)s: 打印日志級(jí)別名稱(chēng)
          • %(pathname)s: 打印當(dāng)前執(zhí)行程序的路徑,其實(shí)就是sys.argv[]
          • %(filename)s: 打印當(dāng)前執(zhí)行程序名
          • %(funcName)s: 打印日志的當(dāng)前函數(shù)
          • %(lineno)d: 打印日志的當(dāng)前行號(hào)
          • %(asctime)s: 打印日志的時(shí)間
          • %(thread)d: 打印線程ID
          • %(threadName)s: 打印線程名稱(chēng)
          • %(process)d: 打印進(jìn)程ID
          • %(message)s: 打印日志信息
          • datefmt: 指定時(shí)間格式并村,同time.strftime()
          • level: 設(shè)置日志級(jí)別巍实,默認(rèn)為logging.WARNING
          • stream: 指定將日志的輸出流,可以指定輸出到sys.stderr,sys.stdout或者文件哩牍,默認(rèn)輸出到sys.stderr棚潦,當(dāng)stream和filename同時(shí)指定時(shí),stream被忽略
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載膝昆,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者瓦盛。
  • 序言:七十年代末洗显,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子原环,更是在濱河造成了極大的恐慌挠唆,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘱吗,死亡現(xiàn)場(chǎng)離奇詭異玄组,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)谒麦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén)俄讹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绕德,你說(shuō)我怎么就攤上這事患膛。” “怎么了耻蛇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵踪蹬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我臣咖,道長(zhǎng)跃捣,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任夺蛇,我火速辦了婚禮疚漆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刁赦。我一直安慰自己娶聘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布甚脉。 她就那樣靜靜地躺著丸升,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宦焦。 梳的紋絲不亂的頭發(fā)上发钝,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音波闹,去河邊找鬼酝豪。 笑死,一個(gè)胖子當(dāng)著我的面吹牛精堕,可吹牛的內(nèi)容都是我干的孵淘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼歹篓,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瘫证!你這毒婦竟也來(lái)了揉阎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤背捌,失蹤者是張志新(化名)和其女友劉穎毙籽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體毡庆,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坑赡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了么抗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毅否。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝇刀,靈堂內(nèi)的尸體忽然破棺而出螟加,到底是詐尸還是另有隱情,我是刑警寧澤吞琐,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布捆探,位于F島的核電站,受9級(jí)特大地震影響顽分,放射性物質(zhì)發(fā)生泄漏徐许。R本人自食惡果不足惜施蜜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一卒蘸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧翻默,春花似錦缸沃、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至肯污,卻和暖如春翘单,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蹦渣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工哄芜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柬唯。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓认臊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親锄奢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子失晴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348