1. 程式人生 > >180120 login 用戶登錄的代碼

180120 login 用戶登錄的代碼

use odin lba lis 指定 常見 文件的 split error

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內置夯實 #當用戶名密碼都正確並且用戶沒被鎖定,打印歡迎界面並退出程序 if
username 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

一些細節

  1. getpass模塊內部其實實現了unix_getpass、win_getpass和fallback_getpass三個函數。在模塊被導入之後會首先對用戶使用的系統進行檢查,將相應的函數賦值給getpass。如果檢查失敗,則將fallback_getpass賦值給getpass。

  2. win_getpass使用msvcrt.getwch()獲取無回顯輸入。

  3. 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 用戶登錄的代碼