111

来源:https://www.cnblogs.com/xiaomage666/archive/2019/05/22/10903568.html
-Advertisement-
Play Games

1. 內容大綱 1. 自定義模塊 2. 模塊是什麼? 3. 為什麼要有模塊? 什麼是腳本? 4. 模塊的分類 5. import的使用 第一次導入模塊執行三件事 被導入模塊有獨立的名稱空間 為模塊起別名 導入多個模塊 6. from ... import ... from ... import .. ...


  1. 內容大綱

    1. 自定義模塊
    2. 模塊是什麼?
    3. 為什麼要有模塊?
      • 什麼是腳本?
    4. 模塊的分類
    5. import的使用
      • 第一次導入模塊執行三件事
      • 被導入模塊有獨立的名稱空間
      • 為模塊起別名
      • 導入多個模塊
    6. from ... import ...
      • from ... import ...的使用
      • from ... import ... 與import對比
      • 一行導入多個
      • from ... import *
      • 模塊迴圈導入的問題
      • py文件的兩種功能
      • 模塊的搜索路徑
    7. json pickle 模塊
    8. hashlib模塊
  2. 具體內容

    1. 自定義模塊:自定義模塊名不能與內置模塊名重名。

    2. 模塊是什麼?

      將20萬行代碼全部放在一個py文件中?為什麼不行?

      1. 代碼太多,讀取代碼耗時太長.
        2. 代碼不容易維護.

      將相同的功能封裝到一個文件中,這個存儲著很多常用的功能的py文件,就是模塊。 模塊就是文件,存放一堆常用的函數,誰用誰拿。一個函數就是一個功能,把一些常用的函數放在一個py文件中,這個文件就稱之為模塊。模塊就是一些常用功能的集合體。

      模塊就是一個py文件,是常用的相似功能的集合.

    3. 為什麼要使用模塊?

      • 拿來主義,提高開發效率.
      • 便於管理維護.

      • 什麼是腳本?
        • 腳本就是py文件,長期保存代碼的文件.
    4. 模塊的分類

      1. 內置模塊,也叫做標準庫。此類模塊就是python解釋器給你提供的,比如我們之前見過的time模塊,os模塊。標準庫的模塊非常多(200多個,每個模塊又有很多功能)

      2. 第三方模塊,第三方庫。一些python大神寫的非常好用的模塊,必須通過pip install 指令安裝的模塊,比如BeautfulSoup, Django,等等。大概有6000多個。

      3. 自定義模塊,我們自己在項目中定義的一些模塊。自己寫的一個py文件。定義一個模塊其實很簡單就是寫一個文件,裡面寫一些代碼(變數,函數)即可

        # xxx.py  (自定義模塊)
        
        #print('from the xxx.py')
        name = '太白金星'
        
        def read1():
            print('xxx模塊:',name)
        
        def read2():
            print('xxx模塊')
            read1()
        
        def change():
            global name
            name = 'barry'
            print(name)
    5. import的使用: 註意:引用模塊寫在最上面,不要寫在函數里。

      import 模塊 先要怎麼樣?

      import xxx 執行一次xxx這個模塊裡面的所有代碼

      ​ 模塊可以包含可執行的語句和函數的定義,這些語句的目的是初始化模塊,它們只在模塊名第一次遇到導入import語句時才執行。

      ​ import語句是可以在程式中的任意位置使用的,且針對同一個模塊import多次,為了防止你重覆導入,python的優化手段是:第一次引用某個模塊,會將這個模塊裡面的所有代碼載入到記憶體,只要你的程式沒有結束,接下來你在引用多少次,它會先從記憶體中尋找有沒有此模塊,如果已經載入到記憶體,就不在重覆載入。後續的import語句僅是對已經載入到記憶體中的模塊對象增加了一次引用,不會重新執行模塊內的語句。

      • 第一次導入模塊執行三件事 ***

          1. 在記憶體中創建一個以被導入模塊名命名的名稱空間.(一個py文件有一個名稱空間

          2. 執行此名稱空間所有的可執行代碼(將xxx.py文件中所有的變數與值的對應關係載入到這個名稱空間).

          3. 通過 模塊名. 的方式引用模塊裡面的內容(變數,函數名,類名等)。 ps:重覆導入會直接引用記憶體中已經載入好的結果

            import xxx
            print(xxx.name)
            xxx.read1()
            

      • 被導入模塊有獨立的名稱空間 ***

        被導入模塊有獨立的名稱空間,它只能操作自己空間中的所有內容,不能操作導入該模塊的py文件中的內容。每個模塊都是一個獨立的全局名稱空間,用來定義這個模塊中的函數,把這個模塊的名稱空間當做全局名稱空間,這樣我們在編寫自己的模塊時,就不用擔心我們定義在自己模塊中全局變數在被導入時,會與使用者的全局變數衝突。
        從基本概念來說, 一個名稱空間就是一個從名稱到對象的關係映射集合。 我們已經明確地知道, 模塊名稱是它們的屬性名稱中的一個重要部分。 例如string 模塊中的 atoi() 函數就是 string.atoi() 。給定一個模塊名之後, 只可能有一個模塊被導入到 Python 解釋器中, 所以在不同模塊間不會出現名稱交叉現象; 所以每個模塊都定義了它自己的唯一的名稱空間。 如果我在我自己的模塊 mymodule 里創建了一個 atoi() 函數, 那麼它的名字應該是 mymodule.atoi() 。 所以即使屬性之間有名稱衝突, 但它們的完整授權名稱(fullyqualified name)——通過句點屬性標識指定了各自的名稱空間 - 防止了名稱衝突的發生。
         #
         import xxx
         name = 'alex'
         print(name)
         print(xxx.name)
         #結果:
          alex
          太白金星
        
         #
         import xxx
         def read1():
             print(666)
         xxx.read1()
        #結果:
        xxx模塊: 太白金星
        
         #
         import xxx
         name = '日天'
         xxx.change()  #barry
         print(name)  # 日天
         print(xxx.name)  # barry

      • 為模塊起別名 **

        • 1 簡單,便捷,將長的模塊名改為短的模塊名

           import xxx as m
           print(m.name)
          #結果:
          太白金星
          
        • 2,有利於代碼的簡化.

          # 原始寫法:
           result = input('請輸入')
           if result == 'mysql':
               import mysql1
               mysql1.mysql()
           elif result == 'oracle':
               import oracle1
               oracle1.oracle()
          
          # 起別名:
           result = input('請輸入')
           if result == 'mysql':
               import mysql1 as m
           elif result == 'oracle':
               import oracle1 as m
             ''' 後面還有很多'''
           m.db()  # 統一介面,歸一化思想
      • 導入多個模塊:多行導入,易於閱讀 ,易於編輯 ,易於搜索 ,易於維護。

        import time, os, sys  # 這樣寫不好
        # 應該向以下這種寫法:
        import time
        import os
        import sys
    6. from ... import ...

      • from ... import ...的使用

         from xxx import name
         from xxx import read1
         from xxx import read2
         print(name)#太白金星
         print(globals())
         read1()#xxx模塊: 太白金星
      • from ... import ... 與import對比 ***

        1. from.. import 用起來更方便,在當前名稱空間中,直接使用名字就可以了,無需加首碼:xxx.

          from xxx import name
          print(name)
        2. from...import 容易與當前執行文件中的名字產生衝突.

          # 容易產生衝突,後者將前者覆蓋。執行文件有與模塊同名的變數或者函數名,會有覆蓋效果
           name = 'alex'
           from xxx import name
           print(name)#太白金星
          
        3. 當前位置直接使用read1和read2,執行時,仍然以xxx.py文件全局名稱空間 ***

          #
          from xxx import read1
          def read1():
              print(666)
          read1()#666 
          
          #
          from xxx import read1
          name = '大壯'
          read1()#xxx模塊: 太白金星
          print(globals())
          
          #
          from xxx import change
          name = 'Alex'
          print(name)  # 'Alex'
          change()  # 'barry'
          from xxx import name
          print(name)#barry
          
           from xxx import change
           name = 'Alex'
           print(name)  # 'Alex'
           change()  # 'barry'
           print(name) # 'Alex'
          
          
      • 一行導入多個

        from tbjx import name,read1,read2  # 這樣不好
        from tbjx import name
        from tbjx import read1
      • from ... import *

        • 把xxx.py中所有的不是以下劃線(_)開頭的名字都導入到當前位置,大部分情況下我們的python程式不應該使用這種導入方式,因為*你不知道你導入什麼名字,很有可能會覆蓋掉你之前已經定義的名字。而且可讀性極其的差。一般千萬別麽這寫,必須要將這個模塊中的所有名字全部記住.但是可以配合一個變數使用

           #  xxx.py
            __all__ = ['name', 'read1']  # 配合*使用    註:沒寫到__all__中的變數,可以單獨引用
          
            name = '太白金星'
          
           def read1():
               print('tbjx模塊:', name)
          
           def read2():
               print('tbjx模塊')
               read1()
           def change():
               global name
               name = 'barry'
               print(name)
      • 模塊迴圈導入的問題:模塊迴圈/嵌套導入拋出異常的根本原因是由於在python中模塊被導入一次之後,就不會重新導入,只會在第一次導入時執行模塊內代碼。在我們的項目中應該儘量避免出現迴圈/嵌套導入,如果出現多個模塊都需要共用的數據,可以將共用的數據集中存放到某一個地方。當程式出現了迴圈/嵌套導入後的異常分析、解決方法如下(瞭解,以後儘量避免

            #創建一個m1.py
                print('正在導入m1') 
                from m2 import y
                x='m1'
        
            #創建一個m2.py
                print('正在導入m2')
                from m1 import x
                y='m2'
        
            #創建一個run.py
                import m1
        
            #測試一
            執行run.py會拋出異常
            正在導入m1
            正在導入m2
            Traceback (most recent call last):
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/aa.py", line 1, in <module>
                import m1
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m1.py", line 2, in <module>
                from m2 import y
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m2.py", line 2, in <module>
                from m1 import x
            ImportError: cannot import name 'x'
        
        
            #測試一結果分析
            先執行run.py--->執行import m1,開始導入m1並運行其內部代碼--->列印內容"正在導入m1"--->執行from m2 import y 開始導入m2並運行其內部代碼--->列印內容“正在導入m2”--->執行from m1 import x,由於m1已經被導入過了,所以不會重新導入,所以直接去m1中拿x,然而x此時並沒有存在於m1中,所以報錯
        
        
            #測試二:執行文件不等於導入文件,比如執行m1.py不等於導入了m1
            直接執行m1.py拋出異常
            正在導入m1
            正在導入m2
            正在導入m1
            Traceback (most recent call last):
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m1.py", line 2, in <module>
                from m2 import y
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m2.py", line 2, in <module>
                from m1 import x
              File "/Users/linhaifeng/PycharmProjects/pro01/1 aaaa練習目錄/m1.py", line 2, in <module>
                from m2 import y
            ImportError: cannot import name 'y'
        
        
            #測試二分析
            執行m1.py,列印“正在導入m1”,執行from m2 import y ,導入m2進而執行m2.py內部代碼--->列印"正在導入m2",執行from m1 import x,此時m1是第一次被導入,執行m1.py並不等於導入了m1,於是開始導入m1並執行其內部代碼--->列印"正在導入m1",執行from m1 import y,由於m1已經被導入過了,所以無需繼續導入而直接問m2要y,然而y此時並沒有存在於m2中所以報
        
        
        # 解決方法:
            方法一:導入語句放到最後
            #m1.py
                print('正在導入m1')
                x='m1'
                from m2 import y
        
            #m2.py
                print('正在導入m2')
                y='m2'
                from m1 import x
        
            方法二:導入語句放到函數中
            #m1.py
                print('正在導入m1')
                def f1():
                    from m2 import y
                    print(x,y)
                x = 'm1'
                # f1()
        
            #m2.py
                print('正在導入m2')
                def f2():
                    from m1 import x
                    print(x,y
                y = 'm2'
        
            #run.py
                import m1
                m1.f1()
      • py文件的兩種功能:

        1. 自己使用, 當做腳本,一個文件就是整個程式,用來被執行

        2. 被別人引用 ,當做模塊使用,文件中存放著一堆功能,用來被導入使用

          python為我們內置了全局變數__name__  
          
          #用來控制.py文件在不同的應用場景下執行不同的邏輯
            print(__name__)
            當tbjx.py做腳本: __name__ == __main__  返回True
            當tbjx.py做模塊被別人引用時: __name__ == xxx(模塊名)
          
           # __name__ 根據文件的扮演的角色(腳本,模塊)不同而得到不同的結果
          
          1, 模塊需要調試時,加上 if __name__ == '__main__':
          
            change()  # 測試代碼
            if __name__ == '__main__':
                change()
          
           2, 作為項目的啟動文件需要用.
          
      • 模塊的搜索路徑 ***
    
            #import abc  abc也是一個內置模塊
            # python 解釋器會自動將一些內置內容(內置函數,內置模塊等等)載入到記憶體中

            import sys
            print(sys.modules)  # 內置內容(內置函數,內置模塊等等)
            print(sys.path)
            #['D:\\python_22\\day17', 'C:\\Python\\Python36\\python36.zip', 'C:\\Python\\Python36\\DLLs', 'C:\\Python\\Python36\\lib', 'C:\\Python\\Python36', 'C:\\Python\\Python36\\lib\\site-packages']

            # 'D:\\python_22\\day17' 路徑是當前執行文件的相對路徑

            #要想導入dz.py模塊: 記憶體中沒有,內置模塊也沒有,這兩個你左右不了,但是sys.path你可以操作.
            import sys
            sys.path.append(r'D:\python_22\day16')  # sys.path 會自動將你的 當前目錄的路徑載入到列表中.  D:\python_22\day16 是dz.py的相對路徑
            import dz
    
    # 如果你想要引用你自定義的模塊:
     要不你就將這個模塊放到當前目錄下麵,要不你就手動添加到sys.path
    
        模塊的查找順序:
    
          Python中引用模塊是按照一定的規則以及順序去尋找的,這個查詢順序為:先從記憶體中已經載入的模塊進行尋找,找不到再從內置模塊中尋找,內置模塊如果也沒有,最後去sys.path中路徑包含的模塊中尋找。它只會按照這個順序從這些指定的地方去尋找,如果最終都沒有找到,那麼就會報錯。

    註意的是:我們自定義的模塊名不應該與系統內置模塊重名

  1. json pickle 模塊

    序列化模塊: 將一種數據結構(list,tuple,dict ....)轉化成特殊的序列。並且這個特殊的序列還可以反解回去。它的主要用途:文件讀寫數據,網路傳輸數據。json pickle shelve

    為什麼存在序列化?

    數據 ----> bytes

    只有字元串類型和bytes可以互換.

    dict,list..... -------> str <--------> bytes

    數據存儲在文件中,str(bytes類型)形式存儲,比如字典.

    數據通過網路傳輸(bytes類型),str 不能還原回去.

特殊的字元串:將一種數據結構(如字典、列表)等轉換成一個特殊的序列(字元串或者bytes)的過程就叫做序列化。如果你寫入文件中的字元串是一個序列化後的特殊的字元串,那麼當你從文件中讀取出來,是可以轉化回原數據結構的。

序列化模塊:

json模塊 : (重點

  1. 不同語言都遵循的一種數據轉化格式,即不同語言都使用的特殊字元串。(比如Python的一個列表[1, 2, 3]利用json轉化成特殊的字元串,然後在編碼成bytes發送給php的開發者,php的開發者就可以解碼成特殊的字元串,然後在反解成原數組(列表): [1, 2, 3])

  2. json序列化只支持部分Python數據結構:dict,list, tuple,str,int, float,True,False,None

  3. json模塊是將滿足條件的數據結構轉化成特殊的字元串,並且也可以反序列化還原回去。序列化模塊總共只有兩種用法,要不就是用於網路傳輸的中間環節,要不就是文件存儲的中間環節,所以json模塊總共就有兩對四個方法:

    用於網路傳輸:dumps、loads

    用於文件寫讀:dump、load

            
         dumps loads 主要用於網路傳輸,但是也可以讀寫文件,但一般用dump,load讀寫文件
               
                 import json
                 dic = {'username': '太白', 'password': 123,'status': True}
                 # 轉化成特殊的字元串
                 st = json.dumps(dic)
                 print(st,type(st))#{"username": "\u592a\u767d", "password": 123, "status": true} <class 'str'>
                 
                 st = json.dumps(dic,ensure_ascii=False)  #不使用ASCII,使用Unicode,可以顯示中文
                 print(st,type(st))#{"username": "太白", "password": 123, "status": true} <class 'str'>
                 #註意,json轉換完的字元串類型的字典中的字元串是由""表示的
                 
                 #反轉回去
                 dic1 = json.loads(st)
                 print(dic1,type(dic1))#{'username': '太白', 'password': 123, 'status': True} <class 'dict'>

                 # 寫入文件
                 l1 = [1, 2, 3, {'name': 'alex'}]#也可以處理嵌套的數據類型 
                # 轉化成特殊的字元串寫入文件
                 with open('json文件',encoding='utf-8',mode='w') as f1:
                     st = json.dumps(l1)  #先轉化成特殊的字元串
                     f1.write(st)

                # 讀取出來還原回去
                 with open('json文件',encoding='utf-8') as f2:
                     st = f2.read()
                     l1 = json.loads(st)
                     print(l1,type(l1))#[1, 2, 3, {'name': 'alex'}] <class 'list'>
            
            
            
            # 特殊的參數:
            ensure_ascii:,當它為True的時候,所有非ASCII碼字元顯示為\uXXXX序列,只需在dump時將ensure_ascii設置為False即可,此時存入json的中文即可正常顯示。 separators:分隔符,實際上是(item_separator, dict_separator)的一個元組,預設的就是(‘,’,’:’);這表示dictionary內keys之間用“,”隔開,而KEY和value之間用“:”隔開。 sort_keys:將數據根據keys的值進行排序。 剩下的自己看源碼研究
            
            

         dump load 只能用於寫入文件,只能寫入一個數據結構
             import json
             l1 = [1, 2, 3, {'name': 'alex'}]
             with open('json文件1.json',encoding='utf-8',mode='w') as f1:  # json文件也是文件,就是專門存儲json字元串的文件。
                 json.dump(l1,f1) # dump方法接收一個文件句柄,直接將l1轉換成json字元串寫入文件

            # 讀取數據
             with open('json文件1.json',encoding='utf-8') as f2:
                 l1 = json.load(f2)# load方法接收一個文件句柄,直接將文件中的json字元串轉換成數據結構返回
                 print(l1,type(l1))#[1, 2, 3, {'name': 'alex'}] <class 'list'>


            # 一次寫入文件多個數據怎麼做?

            # 錯誤示例:
                 dic1 = {'username': 'alex'}
                 dic2 = {'username': '太白'}
                 dic3 = {'username': '大壯'}
                # 寫入數據
                 with open('json文件1',encoding='utf-8',mode='w') as f1:
                     json.dump(dic1,f1)
                     json.dump(dic2,f1)
                     json.dump(dic3,f1)

                # 讀取數據
                 with open('json文件1',encoding='utf-8') as f1:
                     print(json.load(f1))#報錯
                     print(json.load(f1))#報錯
                     print(json.load(f1))#報錯


            # 正確寫法:  用 dumps loads
                 dic1 = {'username': 'alex'}
                 dic2 = {'username': '太白'}
                 dic3 = {'username': '大壯'}
                 with open('json文件1',encoding='utf-8',mode='w') as f1:
                     f1.write(json.dumps(dic1) + '\n')
                     f1.write(json.dumps(dic2) + '\n')
                     f1.write(json.dumps(dic3) + '\n')

                 with open('json文件1',encoding='utf-8') as f1:
                     for i in f1:
                         print(json.loads(i))
                 #結果:
                {'username': 'alex'}
                {'username': '太白'}
                {'username': '大壯'}


pickle模塊

  1. 只能是Python語言遵循的一種數據轉化格式,只能在python語言中使用。

  2. 支持Python所有的數據類型,包括實例化對象。pickle模塊是將Python所有的數據結構以及對象等轉化成bytes類型,然後還可以反序列化還原回去。

    • 用於網路傳輸:dumps、loads
    • 用於文件寫讀:dump、load

            l1 = [1, 2, 3, {'name': 'alex'}]

          dumps loads 只能用於網路傳輸,不能寫入文件
             
             import pickle
             st = pickle.dumps(l1)
             print(st)  # bytes類型   b'\x80\x03]q\x00(K\x01K\x02K\x03}q\x01X\x04\x00\x00\x00nameq\x02X\x04\x00\x00\x00alexq\x03se.'
            
             l2 = pickle.loads(st)
             print(l2,type(l2))#[1, 2, 3, {'name': 'alex'}] <class 'list'>
            
            # 還可以序列化對象
            import pickle
            
            def func():
                print(666)

            ret = pickle.dumps(func)
            print(ret,type(ret))  # b'\x80\x03c__main__\nfunc\nq\x00.' <class 'bytes'>
            
            f1 = pickle.loads(ret)  # f1得到 func函數的記憶體地址
            f1()  # 執行func函數

          
        dump load 直接寫入文件,可以一次寫入多個數據
            
             #pickle序列化存儲多個數據到一個文件中
             import pickle
             dic1 = {'name':'oldboy1'}
             dic2 = {'name':'oldboy2'}
             dic3 = {'name':'oldboy3'}
            
             f = open('pick多數據',mode='wb')
             pickle.dump(dic1,f)
             pickle.dump(dic2,f)
             pickle.dump(dic3,f)
             f.close()
                
             import pickle
             f = open('pick多數據',mode='rb')
             print(pickle.load(f))
             print(pickle.load(f))
             print(pickle.load(f))
             f.close()
             #結果:
            {'name': 'oldboy1'}
            {'name': 'oldboy2'}
            {'name': 'oldboy3'}

            #或者:
            f = open('pick多數據',mode='rb')
            while True:
                try:
                    print(pickle.load(f))
                except EOFError:
                    break
            f.close()
            #結果:
             {'name': 'oldboy1'}
             {'name': 'oldboy2'}
             {'name': 'oldboy3'}   

                
            #可以序列化對象(寫入函數名)
            import pickle
            def func():
                print('in func')

             f = open('pick對象',mode='wb')
             pickle.dump(func,f)  #註意參數順序  函數名func,文件句柄
             f.close()

             f = open('pick對象', mode='rb')
             ret = pickle.load(f)
             print(ret)#<function func at 0x0000020F2F9C1E18>  記憶體地址
             ret()#in func
  1. hashlib模塊

    摘要演算法,也叫做加密演算法,或者是哈希演算法,散列演算法等等,它通過一個函數,把任意長度的數據按照一定規則轉換為一個固定長度的數據串(通常用16進位的字元串表示)。

    hashlib模塊就相當於一個演算法的集合,這裡麵包含著很多的加密演算法. MD5, sha1 sha256 sha512......

    用途:

    1. 密碼加密: 不能以明文的形式存儲密碼,一般我們存儲密碼時都要以密文的形式.比如:太黑|e10adc3949ba59abbe56e057f20f883e
    2. 文件的校驗:文件一致性校驗

    用法:

    1. 將bytes類型位元組 ---> 通過hashlib演算法 ---> 固定長度的16進位數字組成的字元串.
    2. 不同的bytes利用相同的演算法(MD5)轉化成的結果一定不同.
    3. 相同的bytes利用相同的演算法(MD5)轉化成的結果一定相同.
    4. hashlib演算法不可逆(MD5中國王曉雲破解了).

           1.密碼加密:
            # md5
             s1 = 'kfdslfjasdlfgjsdlgkhsdafkshdafjksdfsdkfhjsdafj老fhdskafhsdkjfdsa男孩教育'
             import hashlib
             ret = hashlib.md5()
             ret.update(s1.encode('utf-8'))
            print(ret.hexdigest(),type(ret.hexdigest())) # 18f127c24462dd59287798ea5c0c0c2f <class 'str'>

            # 相關練習
             import hashlib
             def MD5(pwd):
                 ret = hashlib.md5()
                 ret.update(pwd.encode('utf-8'))
                 return ret.hexdigest()
            
            
            #登錄和註冊時密碼加密
            def get_user_pwd():  #獲取用戶名,密碼
                dic1 = {}
                with open('register.text', encoding='utf-8', mode='r+') as f:  # 讀寫模式,先讀後寫,讀並追加
                    for line in f:
                        if line != '\n':
                            line_list = line.strip().split('|')
                            dic1[line_list[0]] = line_list[1]  # 如果有空行,列表元素為空,會報錯。
                    return dic1


            def register():  #註冊
                user_dict = get_user_pwd()
                print(user_dict)
                while 1:
                    username = input('請輸入用戶名:').strip()
                    password = input('請輸入密碼:').strip()
                    password_md5 = _md5_(password)  # 對密碼加密
                    if username not in user_dict:
                        with open('register.text', encoding='utf-8', mode='a') as f:
                            f.write(f'\n{username}|{password_md5}')
                            print('註冊成功')
                            return True
                    else:
                        print('用戶名已經存在')
            # register()


            def login():  #登錄
                user_dict1 = get_user_pwd()
                count = 0
                while count < 3:
                    username = input('請輸入用戶名:').strip()
                    password = input('請輸入密碼:').strip()
                    password_md5 = _md5_(password)
                    if username in user_dict1 and password_md5 == user_dict1[username]:
                        print('登陸成功')
                        return True
                    else:
                        print('用戶名或密碼錯誤')
                        count += 1
            # login()
            
            
            
            # 普通加密
             
             # 123456:  18f127c24462dd59258898ea5c0c0c2f
             # 000000:  18f127c24462dd59258898we5c0c0c2f

             s2 = '19890425'
             ret = hashlib.md5()
             ret.update(s2.encode('utf-8'))
             print(ret.hexdigest())  # 6e942d04cf7ceeeba09e3f2c7c03dc44
            
            普通的md5加密,非常簡單,幾行代碼就可以了,但是這種加密級別是最低的,相對來說不很安全。雖然說hashlib加密是不可逆的加密方式,但也是可以破解的,那麼他是如何做的呢?你看網上好多MD5解密軟體,他們就是用最low的方式,空間換時間。他們會把常用的一些密碼比如:123456,111111,以及他們的md5的值做成對應關係,類似於字典,dic = {'e10adc3949ba59abbe56e057f20f883e': 123456},然後通過你的密文獲取對應的密碼。只要空間足夠大,那麼裡面容納的密碼會非常多,利用空間換取破解時間。 所以針對剛纔說的情況,我們有更安全的加密方式:加鹽。

            # 加鹽

             s2 = '19890425'
             ret = hashlib.md5('太白金星'.encode('utf-8'))#'太白金星'就是固定的鹽
             ret.update(s2.encode('utf-8'))
             print(ret.hexdigest())  # 84c31bbb6f6f494fb12beeb7de4777e1
            
            比如你在一家公司,公司會將你們所有的密碼在md5之前增加一個固定的鹽,這樣提高了密碼的安全性。但是如果黑客通過手段竊取到你這個固定的鹽之後,也是可以破解出來的。所以,我們還可以加動態的鹽。


            # 動態的鹽
             s2 = '19890425'
             ret = hashlib.md5('太白金星'[::2].encode('utf-8'))   #比如用戶名切片,針對於每個賬戶,每個賬戶的鹽都不一樣
             ret.update(s2.encode('utf-8'))
             print(ret.hexdigest())  # 84c31bbb6f6f494fb12beeb7de4777e1


            # sha系列  金融類,安全類.用這個級別.
            hahslib模塊是一個演算法集合,他裡面包含很多種加密演算法,剛纔我們說的MD5演算法是比較常用的一種加密演算法,一般的企業用MD5就夠用了。但是對安全要求比較高的企業,比如金融行業,MD5加密的方式就不夠了,得需要加密方式更高的,比如sha系列,sha1,sha224,sha512等等,數字越大,加密的方法越複雜,安全性越高,越不容易破解,但是效率就會越慢。
            
                 s2 = '198fdsl;fdsklgfjsdlgdsjlfkjsdalfksjdal90425'
                 ret = hashlib.sha3_512()
                 ret.update(s2.encode('utf-8'))
                 print(ret.hexdigest())  # 4d623c6701995c989f400f7e7eef0c4fd4ff15194751f5cb7fb812c7d42a7406ca0349ea3447d245ca29b48a941e2f2f66579fb090babb73eb2b446391a8e102


                 #也可加鹽
                 ret = hashlib.sha384(b'asfdsa')
                 ret.update('taibaijinxing'.encode('utf-8'))
                 print(ret.hexdigest())

                 # 也可以加動態的鹽
                 ret = hashlib.sha384(b'asfdsa'[::2])
                 ret.update('taibaijinxing'.encode('utf-8'))
                 print(ret.hexdigest())



            2.文件的校驗
            

             linux中一切皆文件: 文本文件,非文本文件(我們普通的文件,是文件,視頻,音頻,圖片,以及應用程式等都是文件 )
             無論你下載的視頻,還是軟體(國外的軟體),往往都會有一個md5值,往往都帶有一個MD5或者shax值,當我們下載完成這個應用程式時你要是對比大小根本看不出什麼問題,你應該對比他們的md5值,如果兩個md5值相同,就證明這個應用程式是安全的,如果你下載的這個文件的MD5值與服務端給你提供的不同,那麼就證明你這個應用程式肯定是植入病毒了(文件損壞的幾率很低),那麼你就應該趕緊刪除,不應該安裝此應用程式。

            #官網下載pycharm
            sha256 : 6217ce726fc8ccd48ec76e9f92d15feecd20422c30367c6dc8c222ab352a3ec6  *pycharm-professional-2019.1.2.exe
            
            #直接全部update(類比文件)
             s1 = '我叫太白金星 今年18歲'
             ret = hashlib.sha256()
             ret.update(s1.encode('utf-8'))
             print(ret.hexdigest())  # 54fab159ad8f0bfc5df726a70332f111c2c54d31849fb1e4dc1fcc176e9e4cdc
            
            #分段update(類比文件)
             ret = hashlib.sha256()
             ret.update('我叫'.encode('utf-8'))
             ret.update('太白金星'.encode('utf-8'))
             ret.update(' 今年'.encode('utf-8'))
             ret.update('18歲'.encode('utf-8'))
             print(ret.hexdigest())  # 54fab159ad8f0bfc5df726a70332f111c2c54d31849fb1e4dc1fcc176e9e4cdc
            #結果相同

            # low版校驗:
            def file_md5(path):
                ret = hashlib.sha256()
                with open(path,mode='rb') as f1:  #以rb方式讀取
                    b1 = f1.read()  #文件過大會撐爆記憶體
                    ret.update(b1)
                return ret.hexdigest()
            result = file_md5('pycharm-professional-2019.1.2.exe')
            print(result)  # 6217ce726fc8ccd48ec76e9f92d15feecd20422c30367c6dc8c222ab352a3ec6
            #上面這樣寫有一個問題,類似我們文件的改的操作,有什麼問題?如果文件過大,全部讀取出來直接就會撐爆記憶體的,所以我們要分段讀取,那麼分段讀取怎麼做呢?
            
            # 高大上版:
            def file_check(file_path):
            with open(file_path,mode='rb') as f1:
                sha256 = hashlib.sha256()
                while 1:
                    content = f1.read(1024)
                    if content:
                        sha256.update(content)
                    else:
                        return sha256.hexdigest()
            print(file_check('pycharm-professional-2019.1.1.exe'))

總結

  1. import 三件事, import的名字如果調用? 模塊名.的方式調用.

  2. from ... import ... 容易產生衝突,獨立的空間.

  3. __name__問題

  4. 模塊的搜索路徑

    記憶體 內置 sys.path

  5. 序列化模塊:

    1. json最最常用(兩對四個方法就行) 一定要掌握
    2. pickle(兩對四個方法就行) 儘量掌握
  6. hashlib

    1. 密碼的加密 ,文件的校驗


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1,重載是 C 語言到 C++ 語言的一個飛躍,C 語言中沒有重載的概念,所有的函數 名是不允許有重覆的,在 C++ 中因為引進了重載,所以函數名可以重覆; 2,自然語言中的上下文: 1,你知道上面辭彙中“洗”字的含義嗎? 1,不同的動詞和名次搭配的含義是不同的; 2,結論: 1,能和“洗”字搭配的 ...
  • 工作之餘在知乎上偶然看到一篇回帖,瞬間覺得之前看的那麼多資料都不及這一篇讓我對 websocket 的認知深刻易懂,之前看總完總覺得一知半解雲里霧裡。所以與大家共同分享一下一起學習。比較喜歡這種博客理論和小故事的事例結合,讀起來很輕鬆,不枯燥。廢話不多說了,進入正題了~ 一、websocket與ht ...
  • 發佈與訂閱消息系統 在正式討論Apache Kafka (以下簡稱Kafka)之前,先來瞭解發佈與訂閱消息系統的概念, 並認識這個系統的重要性。數據(消息)的發送者(發佈者)不會直接把消息發送給接收 者,這是發佈與訂閱消息系統的一個特點。發佈者以某種方式對消息進行分類,接收者 (訂閱者)訂閱它們,以 ...
  • [toc] 這篇文章主要講 map 的賦值、刪除、查詢、擴容的具體執行過程,仍然是從底層的角度展開。結合源碼,看完本文一定會徹底明白 map 底層原理。 我要說明的是,這裡對 map 的基本用法涉及比較少,我相信可以通過閱讀其他入門書籍瞭解。本文的內容比較深入,但是由於我畫了各種圖,我相信很容易看懂 ...
  • JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? JVM記憶體分為哪幾部分?各個部分的作用是什麼? 1. Java虛擬機記憶體的五大區域 Java的運行離不開Java虛擬機的支持,今天我就跟大家探討一下Java ...
  • 厲害了,2019/05/21 Apache軟體基金會發表博文,宣佈 Dubbo 在 2019/05/20 這天正式畢業,成為 Apache 的頂級項目。 參考:https://blogs.apache.org/foundation/entry/the apache software foundati ...
  • 14.1 基本介紹 -Scala飾運行在Java虛擬機(Java Virtual Machine)之上,因此具有如下特點 1) 輕鬆實現和豐富的Java類庫互聯互通 2) 它既支持面向對象的編程方式,又支持函數式編程 3) 它寫出的程式像動態語言一樣簡潔,但事實上它確是嚴格意義上的靜態語言 14.2 ...
  • Collection集合 數組的長度是固定的,集合的長度是可變的 數組中存儲的是同一類型的元素,可以存儲基本數據類型值。集合存儲的都是對象。而且對象的類型可以不一致。 集合框架 java import java.util. ; public class IteratorDemo{ public st ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...