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(' ').split('|')[0]) #往列表添加 pass_list.append(line.strip(' ').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(' ')) #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+' ') 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()) # 把末尾的' '删掉
写文件
写文件和读文件是一样的,唯一区别是调用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行,内部实现非常简单。但模块内部有很多处理异常情况的代码,很多细节没办法在博客里面展开细说,说了显得啰嗦,不像是笔记。所以建议有兴趣的读者花点时间阅读一下源码,能对模块的细节有更充分的理解。