Python-模組,python模組下載
一、模組
1. 什麼是模組
在電腦程式的開發過程中,隨著程式碼越寫越多,在一個檔案裡代碼就會越來越長,越來越不容易維護。
為了編寫可維護的代碼,我們把很多函數分組,分別放到不同的檔案裡,這樣,每個檔案包含的代碼就相對較少,很多程式設計語言都採用這種組織代碼的方式。在Python中,一個.py檔案就稱之為一個模組(Module)。
2. 使用模組的好處
最大的好處是大大提高了代碼的可維護性。其次,編寫代碼不必從零開始。當一個模組編寫完畢,就可以被其他地方引用。我們在編寫程式的時候,也經常引用其他模組,包括Python內建的模組和來自第三方的模組。
使用模組還可以避免函數名和變數名衝突。相同名字的函數和變數完全可以分別存在不同的模組中,因此,我們自己在編寫模組時,不必考慮名字會與其他模組衝突。但是也要注意,盡量不要與內建函數名字衝突。點這裡查看Python的所有內建函數。
3. 使用模組
Python本身就內建了很多非常有用的模組,只要安裝完畢,這些模組就可以立刻使用。
我們以內建的sys模組為例,編寫一個hello的模組:
1 # !/usr/bin/env python3 #該行注釋可以使本檔案直接在Unix/Linux/Mac上運行 2 # -*- coding: utf-8 -*- #該行注釋表示檔案本身使用標準UTF-8編碼 3 4 ' a test module ' #表示模組的文檔注釋,任何模組代碼的第一個字串都被視為模組的文檔注釋 5 6 __author__ = 'Michael Liao' #使用__author__變數將作者寫入檔案 7 8 import sys #匯入內建模組sys(使用模組的方式) 9 10 11 def test():12 args = sys.argv #調用sys模組的argv屬性,該變數以列表的形式儲存命令列的所有參數13 if len(args) == 1:14 print('Hello, world!')15 elif len(args) == 2:16 print('Hello, %s!' % args[1])17 else:18 print('Too many arguments!')19 20 21 if __name__ == '__main__': #當我們在命令列運行hello模組檔案時,Python解譯器把一個特殊變數__name__置為__main__,而如果在其他地方匯入該hello模組時,if判斷將失敗,22 # 因此,這種if測試可以讓一個模組通過命令列運行時執行一些額外的代碼,最常見的就是運行測試。23 test()建立hello模組
4. 安裝第三方模組
在Python中,安裝第三方模組,是通過包管理工具pip完成的。
#在命令列模式下運行:Pillow為第三方的模組名稱pip install Pillow
5. 模組搜尋路徑
當我們試圖載入一個模組時,Python會在指定的路徑下搜尋對應的.py檔案,如果找不到,就會報錯,如所示,import hello報錯
預設情況下,Python解譯器會搜尋目前的目錄、所有已安裝的內建模組和第三方模組,搜尋路徑存放在sys模組的path變數中:
>>> import sys>>> sys.path['', 'C:\\Python36\\python36.zip', 'C:\\Python36\\DLLs', 'C:\\Python36\\lib', 'C:\\Python36', 'C:\\Python36\\lib\\site-packages']>>>
如果我們要添加自己的搜尋目錄,有兩種方法:
一是直接修改sys.path,添加要搜尋的目錄:
>>> import sys>>> sys.path.append('要搜尋的目錄')
這種方法是在運行時修改,運行結束後失效。
第二種方法是設定環境變數PYTHONPATH,該環境變數的內容會被自動添加到模組搜尋路徑中。設定方式與設定Path環境變數類似。注意只需要添加你自己的搜尋路徑,Python自己本身的搜尋路徑不受影響。
二、常用模組
1. time
a. 在Python中,通常有這三種方式來表示時間:時間戳記、元組(struct_time)、格式化的時間字串:
import time#時間戳記(timestamp) 通常來說,時間戳記表示的是從1970年1月1日00:00:00開始按秒計算的位移量。我們運行“type(time.time())”,返回的是float類型。time.time()1493207044.6561139#格式化的時間字串(Format String): time.strftime('%Y-%m-%d %X')'2017-04-26 19:47:54'#元組(struct_time) :struct_time元組共有9個元素:(年,月,日,時,分,秒,本周的第幾天(周一為0),本年的第幾天,時區)time.localtime()time.struct_time(tm_year=2017, tm_mon=4, tm_mday=26, tm_hour=19, tm_min=48, tm_sec=23, tm_wday=2, tm_yday=116, tm_isdst=0)
小結:時間戳記是電腦能夠識別的時間;時間字串是人能夠看懂的時間;元組則是用來操作時間的
b. 時間形式的轉換
#時間戳記--->結構化時間time.localtime()time.struct_time(tm_year=2017, tm_mon=4, tm_mday=26, tm_hour=19, tm_min=57, tm_sec=38, tm_wday=2, tm_yday=116, tm_isdst=0)time.gmtime()time.struct_time(tm_year=2017, tm_mon=4, tm_mday=26, tm_hour=11, tm_min=57, tm_sec=48, tm_wday=2, tm_yday=116, tm_isdst=0)#結構化時間--->時間戳記time.mktime(time.localtime())1493208155.0time.mktime(time.gmtime())1493179366.0#結構化時間--->字串時間time.strftime('%Y-%m-%d %X', time.localtime())'2017-04-26 20:04:22'#字串時間--->結構化時間time.strptime('2017-04-27', '%Y-%m-%d')time.struct_time(tm_year=2017, tm_mon=4, tm_mday=27, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=117, tm_isdst=-1)
c. asctime and ctime
#結構化的時間--->字串時間time.asctime(time.localtime(1493208155.0))'Wed Apr 26 20:02:35 2017'#時間戳記--->字串時間time.ctime(1493208155.0)'Wed Apr 26 20:02:35 2017'
2. random
import random#隨機小數x: 0<x<1random.random()0.9354224633786534#隨機整數x: 1<=x<=10random.randint(1,10)1#隨機整數x: 3=<x<5random.randrange(3,5)3#隨機返回列表中的任一元素random.choice([1,'23',[4,5]])1#隨機返回列表中的任一元素random.choice([1,'23',[4,5]])[4, 5]#隨機返回列表中的任2元素random.sample([2,'a',33,['b',56],7],2)['a', 7]#隨機小數x: 1<x<3random.uniform(1,3)1.8055721248003096#將列表中的元素打亂item = [1,3,5,7,9] #打亂前random.shuffle(item)item[9, 3, 5, 1, 7] #打亂後
練習:
1 import random 2 3 def v_code(): 4 5 “”“根據ASCII碼定製5位隨機字元驗證碼”“” 6 code = '' 7 for i in range(5): 8 a = random.randint(48, 57) # 數字0-9 9 b = random.randint(65, 90) # 大寫字母A-Z10 c = random.randint(97, 122) # 小寫字母a-z11 d = random.choice([a, b, c]) #隨機返回以上3個範圍的數字12 code = ''.join([code, chr(d)])13 14 return code15 16 17 print(v_code())
5位字元的隨機驗證碼
3. hashlib
a. 演算法介紹
Python的hashlib提供了常見的摘要演算法,如MD5,SHA1等等。
什麼是摘要演算法呢?摘要演算法又稱雜湊演算法、散列演算法。它通過一個函數,把任意長度的資料轉換為一個長度固定的資料串(通常用16進位的字串表示)。
摘要演算法就是通過摘要函數f()對任意長度的資料data計算出固定長度的摘要digest,目的是為了發現未經處理資料是否被人篡改過。
摘要演算法之所以能指出資料是否被篡改過,就是因為摘要函數是一個單向函數,計算f(data)很容易,但通過digest反推data卻非常困難。而且,對未經處理資料做一個bit的修改,都會導致計算出的摘要完全不同。
我們以常見的摘要演算法MD5為例,計算出一個字串的MD5值:
1 import hashlib2 3 md5 = hashlib.md5()4 md5.update('Hello world!'.encode('utf-8'))5 print(md5.hexdigest())6 7 #結果:8 #86fb269d190d2c85f6e0468ceca42a20
如果資料量很大,可以分塊多次調用update(),最後計算的結果是一樣的:
1 import hashlib2 3 md5 = hashlib.md5()4 md5.update('Hello '.encode('utf-8')) #注意:Hello後面有一個空格5 md5.update('world!'.encode('utf-8'))6 print(md5.hexdigest())7 8 #結果:9 #86fb269d190d2c85f6e0468ceca42a20
MD5是最常見的摘要演算法,速度很快,產生結果是固定的128 bit位元組,通常用一個32位的16進位字串表示。另一種常見的摘要演算法是SHA1,調用SHA1和調用MD5完全類似:
1 import hashlib 2 3 sha1 = hashlib.sha1() 4 sha1.update('Hello '.encode('utf-8')) # 5 sha1.update('world!'.encode('utf-8')) 6 print(sha1.hexdigest()) 7 8 sha2 = hashlib.sha1() 9 sha2.update('Hello world!'.encode('utf-8'))10 print(sha2.hexdigest())11 12 #結果:13 #d3486ae9136e7856bc42212385ea79709447580214 #d3486ae9136e7856bc42212385ea797094475802
SHA1的結果是160 bit位元組,通常用一個40位的16進位字串表示。比SHA1更安全的演算法是SHA256和SHA512,不過越安全的演算法越慢,而且摘要長度更長。
b. 演算法應用
任何允許使用者登入的網站都會儲存使用者登入的使用者名稱和口令。如何儲存使用者名稱和口令呢?方法是存到資料庫表中:
name | password--------+----------michael | 123456bob | abc999alice | alice2008
如果以明文儲存使用者口令,如果資料庫泄露,所有使用者的口令就落入駭客的手裡。此外,網站營運人員是可以訪問資料庫的,也就是能擷取到所有使用者的口令。正確的儲存口令的方式是不儲存使用者的明文口令,而是儲存使用者口令的摘要,比如MD5:
username | password---------+---------------------------------michael | e10adc3949ba59abbe56e057f20f883ebob | 878ef96e86145580c38c87f0410ad153alice | 99b1c2188db85afee403b1536010c2c9
考慮這麼個情況,很多使用者喜歡用123456,888888,password這些簡單的口令,於是,駭客可以事先計算出這些常用口令的MD5值,得到一個反推表:
'e10adc3949ba59abbe56e057f20f883e': '123456''21218cca77804d2ba1922c33e0151105': '888888''5f4dcc3b5aa765d61d8327deb882cf99': 'password'
這樣,無需破解,只需要對比資料庫的MD5,駭客就獲得了使用常用口令的使用者帳號。
對於使用者來講,當然不要使用過於簡單的口令。但是,我們能否在程式設計上對簡單口令加強保護呢?
由於常用口令的MD5值很容易被計算出來,所以,要確儲存儲的使用者口令不是那些已經被計算出來的常用口令的MD5,這一方法通過對原始口令加一個複雜字串來實現,俗稱“加鹽”:
hashlib.md5("salt".encode("utf8"))
經過Salt處理的MD5口令,只要Salt不被駭客知道,即使使用者輸入簡單口令,也很難通過MD5反推明文口令。
但是如果有兩個使用者都使用了相同的簡單口令比如123456,在資料庫中,將儲存兩條相同的MD5值,這說明這兩個使用者的口令是一樣的。有沒有辦法讓使用相同口令的使用者儲存不同的MD5呢?
如果假定使用者無法修改登入名稱,就可以通過把登入名稱作為Salt的一部分來計算MD5,從而實現相同口令的使用者也儲存不同的MD5。
摘要演算法在很多地方都有廣泛的應用。要注意摘要演算法不是密碼編譯演算法,不能用於加密(因為無法通過摘要反推明文),只能用於防篡改,但是它的單向計算特性決定了可以在不儲存明文口令的情況下驗證使用者口令。
4. os
1 ''' 2 os.getcwd() 擷取當前工作目錄,即當前python指令碼工作的目錄路徑 3 os.chdir("dirname") 改變當前指令碼工作目錄;相當於shell下cd 4 os.curdir 返回目前的目錄: ('.') 5 os.pardir 擷取目前的目錄的父目錄字元串名:('..') 6 os.makedirs('dirname1/dirname2') 可產生多層遞迴目錄 7 os.removedirs('dirname1') 若目錄為空白,則刪除,並遞迴到上一級目錄,如若也為空白,則刪除,依此類推 8 os.mkdir('dirname') 產生單級目錄;相當於shell中mkdir dirname 9 os.rmdir('dirname') 刪除單級空目錄,若目錄不為空白則無法刪除,報錯;相當於shell中rmdir dirname10 os.listdir('dirname') 列出指定目錄下的所有檔案和子目錄,包括隱藏檔案,並以列表方式列印11 os.remove() 刪除一個檔案12 os.rename("oldname","newname") 重新命名檔案/目錄13 os.stat('path/filename') 擷取檔案/目錄資訊14 os.sep 輸出作業系統特定的路徑分隔字元,win下為"\\",Linux下為"/"15 os.linesep 輸出當前平台使用的行終止符,win下為"\t\n",Linux下為"\n"16 os.pathsep 輸出用於分割檔案路徑的字串 win下為;,Linux下為:17 os.name 輸出字串指示當前使用平台。win->'nt'; Linux->'posix'18 os.system("bash command") 運行shell命令,直接顯示19 os.environ 擷取系統內容變數20 os.path.abspath(path) 返回path正常化的絕對路徑21 os.path.split(path) 將path分割成目錄和檔案名稱二元組返回22 os.path.dirname(path) 返回path的目錄。其實就是os.path.split(path)的第一個元素23 os.path.basename(path) 返回path最後的檔案名稱。如何path以/或\結尾,那麼就會返回空值。即os.path.split(path)的第二個元素24 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False25 os.path.isabs(path) 如果path是絕對路徑,返回True26 os.path.isfile(path) 如果path是一個存在的檔案,返回True。否則返回False27 os.path.isdir(path) 如果path是一個存在的目錄,則返回True。否則返回False28 os.path.join(path1[, path2[, ...]]) 將多個路徑組合後返回,第一個絕對路徑之前的參數將被忽略29 os.path.getatime(path) 返回path所指向的檔案或者目錄的最後存取時間30 os.path.getmtime(path) 返回path所指向的檔案或者目錄的最後修改時間31 os.path.getsize(path) 返回path的大小32 '''
5. sys
sys.argv 命令列參數List,第一個元素是程式本身路徑sys.exit(n) 退出程式,正常退出時exit(0)sys.version 擷取Python解釋程式的版本資訊sys.maxint 最大的Int值sys.path 返回模組的搜尋路徑,初始化時使用PYTHONPATH環境變數的值sys.platform 返回作業系統平台名稱
參考資料:
1. http://www.cnblogs.com/yuanchenqi/articles/6766020.html
2. http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431845183474e20ee7e7828b47f7b7607f2dc1e90dbb000