open函数是python的一个内置函数,用于打开一个文件,创建一个 file 对象。
但是,你真的懂open函数吗?
先来看看网上的教程:
函数语法
open(name[, mode[, buffering]])
参数说明:
-
name : 一个包含了你要访问的文件名称的字符串值。
-
mode : mode 决定了打开文件的模式:只读,写入,追加等。所有可取值见如下的完全列表。这个参数是非强制的,默认文件访问模式为只读(r)。
-
buffering : 如果 buffering 的值被设为 0,就不会有寄存。如果 buffering 的值取 1,访问文件时会寄存行。如果将 buffering 的值设为大于 1 的整数,表明了这就是的寄存区的缓冲大小。如果取负值,寄存区的缓冲大小则为系统默认。
不同模式打开文件的完全列表:
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
file 对象方法
-
file.read([size]):size 未指定则返回整个文件,如果文件大小 >2 倍内存则有问题,f.read()读到文件尾时返回""(空字串)。
-
file.readline():返回一行。
-
file.readlines([size]) :返回包含size行的列表, size 未指定则返回全部行。
-
for line in f: print line :通过迭代器访问。
-
f.write("hello\n"):如果要写入字符串以外的数据,先将他转换为字符串。
-
f.tell():返回一个整数,表示当前文件指针的位置(就是到文件头的比特数)。
-
f.seek(偏移量,[起始位置]):用来移动文件指针。
-
偏移量: 单位为比特,可正可负
-
起始位置: 0 - 文件头, 默认值; 1 - 当前位置; 2 - 文件尾
-
-
f.close() 关闭文件
看完了教程,有编程经验的人是不是觉得so easy,我也觉得非常的简单。
但是,我在工作中就掉进了这个坑里,只能说自己对open函数理解的还不够,也说明了自己的基础确实不好。唉,要好好补补基础了,基础扎实才走得稳走得远呀!
先来看看导致bug的代码吧
cache_dir = os.path.join(os.path.dirname(__file__), '../../', 'cache')
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
cache_path = os.path.join(cache_dir, 'sign_token_ticket.json')
if not os.path.exists(cache_path):
with open(cache_path, 'w') as f:
sign_token_ticket = dict(
token={
'value': '',
'expire': 0
},
ticket = {
'value': '',
'expire': 0
}
)
else:
with open(cache_path) as f:
if f.read():
sign_token_ticket = json.loads(f.read())
else:
sign_token_ticket = dict(
token={
'value': '',
'expire': 0
},
ticket={
'value': '',
'expire': 0
}
)
这是一段缓存token的逻辑代码,用来保存有效期的token,如果失效就重新获取,本来是打算存储到数据库的,但是有点用杀牛刀来宰鸡的感觉,所以就保存在文件里。不知道看完代码后的你,有没有发现问题在哪里。
就是以上代码导致bug的出现,我先判断文件里有没有内容,如果有内容就获取文件里的内容。
殊不知,在第一次使用f.read()的时候,文件指针就指向了文件尾,再次使用f.read()读取内容的时候就为空了。
这就是忽略了细节,和基础不扎实,哭唧唧。
既然发现了问题,那就改吧,先读取到内容赋值给一个变量,再对这个变量做判断,这样就可以做到只读一次。
关注公众号:日常bug,每天至少一篇技术文章,适合技术点滴积累,利用琐碎时间学习技术的人。