180120 login 用戶登錄的代碼
import getpass #導入getpass 內置模塊 #定義用戶名、密碼列表 allow_user_list = [] #定義一個空列表 ,名字是allow... pass_list = [] #同上,空列表 #定義被鎖定列表 deny_user_list = [] #同上 #讀取用戶名密碼文件並輸出到字典中 with open(‘allow_user‘,‘r‘) as f: #關於with open 在下面有詳細解釋。 for line in f.readlines(): #再度看到生成器的for計數循環 allow_user_list.append(line.strip(‘\n‘).split(‘|‘)[0]) #往列表添加 pass_list.append(line.strip(‘\n‘).split(‘|‘)[1]) #同上 user_pass = dict(zip(allow_user_list,pass_list)) #定義一個變量 #讀取被鎖定用戶文件並輸出到列表中 with open(‘deny_user‘,‘r‘) as f: for line in f.readlines(): deny_user_list.append(line.strip(‘\n‘)) #line.strip 大概是去掉空格和空行#初始化標記 flag_num = 0 #登錄開始,循環 while flag_num < 3: #輸入登錄用戶名 username = input(‘請輸入用戶名:‘) #輸入登錄密碼 #password = getpass.getpass(‘請輸入密碼:‘) #這大概是首次在代碼塊中看到getpass,這個getpass模塊還有一個getuser的函數。 password = input(‘請輸入密碼:‘) #獲取用戶的輸入的密碼,input內置夯實 #當用戶名密碼都正確並且用戶沒被鎖定,打印歡迎界面並退出程序 ifusername in user_pass and password == user_pass[username] and username not in deny_user_list: #這裏有個if...in...and...==...and...not in.. print (‘‘‘ 登錄成功 歡迎你,%s ‘‘‘ % username) break #當用戶名密碼都正確但用戶已被鎖定,打印用戶已被鎖定 elif username in user_pass and password == user_pass[username] and username in deny_user_list: #同上 print (‘該用戶已被鎖定‘) flag_num += 1 #當用戶名不存在時,打印用戶名不存在 elif username not in user_pass: print (‘該用戶不存在‘) flag_num += 1 #當用戶存在並且沒被鎖定,但密碼錯誤,打印密碼錯誤 else: print (‘密碼錯誤‘) flag_num +=1 #輸入錯誤三次後用戶被鎖定 else: if username not in deny_user_list and username in allow_user_list: with open(‘deny_user‘,‘a‘) as f: f.write(username+‘\n‘) print (‘錯誤輸入三次,該用戶已被鎖定‘) elif username in allow_user_list: print (‘錯誤輸入三次,該用戶已是被鎖定狀態‘) else: print (‘錯誤輸入三次,該用戶不存在無法鎖定‘) #疑問?哪裏看到了3次的限制代碼語句??
讀寫文件是最常見的IO操作。Python內置了讀寫文件的函數,用法和C是兼容的。
讀寫文件前,我們先必須了解一下,在磁盤上讀寫文件的功能都是由操作系統提供的,現代操作系統不允許普通的程序直接操作磁盤,所以,讀寫文件就是請求操作系統打開一個文件對象(通常稱為文件描述符),然後,通過操作系統提供的接口從這個文件對象中讀取數據(讀文件),或者把數據寫入這個文件對象(寫文件)。
讀文件
要以讀文件的模式打開一個文件對象,使用Python內置的open()
函數,傳入文件名和標示符:
>>> f = open(‘/Users/michael/test.txt‘, ‘r‘)
標示符‘r‘表示讀,這樣,我們就成功地打開了一個文件。
如果文件不存在,open()
函數就會拋出一個IOError
的錯誤,並且給出錯誤碼和詳細的信息告訴你文件不存在:
>>> f=open(‘/Users/michael/notfound.txt‘, ‘r‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> FileNotFoundError: [Errno 2] No such file or directory: ‘/Users/michael/notfound.txt‘
如果文件打開成功,接下來,調用read()
方法可以一次讀取文件的全部內容,Python把內容讀到內存,用一個str
對象表示:
>>> f.read() ‘Hello, world!‘
最後一步是調用close()
方法關閉文件。文件使用完畢後必須關閉,因為文件對象會占用操作系統的資源,並且操作系統同一時間能打開的文件數量也是有限的:
>>> f.close()
由於文件讀寫時都有可能產生IOError
,一旦出錯,後面的f.close()
就不會調用。所以,為了保證無論是否出錯都能正確地關閉文件,我們可以使用try ... finally
來實現:
try: f = open(‘/path/to/file‘, ‘r‘) print(f.read()) finally: if f: f.close()
但是每次都這麽寫實在太繁瑣,所以,Python引入了with
語句來自動幫我們調用close()
方法:
with open(‘/path/to/file‘, ‘r‘) as f: print(f.read())
這和前面的try ... finally
是一樣的,但是代碼更佳簡潔,並且不必調用f.close()
方法。
調用read()
會一次性讀取文件的全部內容,如果文件有10G,內存就爆了,所以,要保險起見,可以反復調用read(size)
方法,每次最多讀取size個字節的內容。另外,調用readline()
可以每次讀取一行內容,調用readlines()
一次讀取所有內容並按行返回list
。因此,要根據需要決定怎麽調用。
如果文件很小,read()
一次性讀取最方便;如果不能確定文件大小,反復調用read(size)
比較保險;如果是配置文件,調用readlines()
最方便:
for line in f.readlines(): print(line.strip()) # 把末尾的‘\n‘刪掉
寫文件
寫文件和讀文件是一樣的,唯一區別是調用open()
函數時,傳入標識符‘w‘
或者‘wb‘
表示寫文本文件或寫二進制文件:
>>> f = open(‘/Users/michael/test.txt‘, ‘w‘) >>> f.write(‘Hello, world!‘) >>> f.close()
你可以反復調用write()
來寫入文件,但是務必要調用f.close()
來關閉文件。當我們寫文件時,操作系統往往不會立刻把數據寫入磁盤,而是放到內存緩存起來,空閑的時候再慢慢寫入。只有調用close()
方法時,操作系統才保證把沒有寫入的數據全部寫入磁盤。忘記調用close()
的後果是數據可能只寫了一部分到磁盤,剩下的丟失了。所以,還是用with
語句來得保險:
with open(‘/Users/michael/test.txt‘, ‘w‘) as f: f.write(‘Hello, world!‘)
要寫入特定編碼的文本文件,請給open()
函數傳入encoding
參數,將字符串自動轉換成指定編碼
=======================================================================
描述
Python strip() 方法用於移除字符串頭尾指定的字符(默認為空格)。
語法
strip()方法語法:
str.strip([chars]);
line.strip()會把‘\\n‘(空行)替換為
-------------------------------------------------------------------------------------
getpass模塊
昨天跟學弟吹牛b安利Python標準庫官方文檔的時候偶然發現了這個模塊。仔細一看內容挺少的,只有兩個主要api,就花了點時間閱讀了一下源碼,感覺挺實用的,在這安利給大家。
getpass.getpass(prompt=’Password: ‘, stream=None)
調用該函數可以在命令行窗口裏面無回顯輸入密碼。參數prompt代表提示字符串,默認是’Password: ‘。在Unix系統中,stream默認為當前控制的終端。在Windows系統裏stream參數會被忽略掉,默認使用stdin。如果無法正常使用getpass,會打印錯誤信息,然後模塊會使用有回顯的模式讀取數據。
>>> import getpass
>>> passwd = getpass.getpass()
Password:
>>> print(passwd)
ganziqim
- 1
- 2
- 3
- 4
- 5
getpass.getuser()
返回當前用戶名。這個函數會按順序檢查環境變量LOGNAME, USER, LNAME和USERNAME。返回第一個非空的值。如果檢查不到非空的值,模塊會嘗試導入pwd模塊,如果系統支持pwd模塊,會返回通過pwd模塊獲取的用戶名,否則報錯。
>>> getpass.getuser()
‘ganzi‘
- 1
- 2
一些細節
-
getpass模塊內部其實實現了unix_getpass、win_getpass和fallback_getpass三個函數。在模塊被導入之後會首先對用戶使用的系統進行檢查,將相應的函數賦值給getpass。如果檢查失敗,則將fallback_getpass賦值給getpass。
-
win_getpass使用msvcrt.getwch()獲取無回顯輸入。
-
fallback_getpass不僅在一開始檢查系統的時候被調用,當另外兩個函數出現錯誤的時候也會調用它。而調用了fallback_getpass又會先打印錯誤信息,然後再調用模塊內部的_raw_input函數進行有回顯的輸入讀取。
這個是寫在模塊底部的系統檢查代碼:
try:
import termios
termios.tcgetattr, termios.tcsetattr
except (ImportError, AttributeError):
try:
import msvcrt
except ImportError:
getpass = fallback_getpass
else:
getpass = win_getpass
else:
getpass = unix_getpass
- 總結:getpass模塊只有不到200行代碼(包括註釋和模塊文檔),getuser的主要代碼更是只有短短7行,內部實現非常簡單。但模塊內部有很多處理異常情況的代碼,很多細節沒辦法在博客裏面展開細說,說了顯得啰嗦,不像是筆記。所以建議有興趣的讀者花點時間閱讀一下源碼,能對模塊的細節有更充分的理解。
180120 login 用戶登錄的代碼