Python作为一门动态语言,读写文件来处理数据是它的一门优势,扬长避短地发挥语言的优势才是省时省力的秘诀。文件IO掌握了能用来干什么?实际上有很多用处,举一些实际上的例子,运营策划给一份数据让导入,这时候就涉及到数据文件的读取了。相对来说,Python文件IO真的很简单,大部分都是按行处理,这样的话几乎就没有什么学习难度。
1. 基本使用
open
和close
就是打开和关闭,看看例子:
f = open("readMe.txt", "r")
f.close()
如果用with语句可以安全关闭文件描述符,同样也老是记住要关闭文件描述符。下面离开with语句块之后,f会自动关闭,能用这种方式就尽量用这种方式
# with 代码块
with open("readMe.txt", "r") as f:
for line in f:
print(line.strip())
写入文件:
with open("write.log", "w") as f:
f.write("test\n")
读文件:
# for循环
for line in f:
# 不用strip()会多打印一个换行符
print(line.strip())
# 全部内容都读
content = f.read()
# 一行行读
line = f.readline()
把文件游标移动指定位置,offet是偏移位置,whence有三个参数:
-
0
:默认值,从文件头开始偏移 -
1
: 从当前位置偏移 -
2
: 从文件末尾偏移
f.seek(offet,[whence])
获取文件当前位置:
f.tell()
强制把刷新缓冲,使用write的时候,write有一定缓冲,这样子可以批量写,但如果想立刻看到文件写入的内容,就可能需要下面这个函数了
f.flush()
2. 例1: 日志监控
文件读写的函数很多,但使用到的比较少,用实际例子来理解会更好。下面的例子是实际生产环境监控日志的脚本简化版,核心内容都在里面,读取出来的内容可以根据需要写处理函数进行报警或者统计等。例如发现ERROR这个词,就可以把这条日志发短信到开发的手机上,让他能立刻处理。
先模拟一个定时写入日志的脚本,它会自动在当前目录写一个today.log
的日志
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import time
import random
def main():
with open("today.log", "w+") as f:
for i in xrange(1000000):
for j in xrange(random.randint(1,10)):
f.write("{0}\n".format(j))
f.flush()
time.sleep(1)
if __name__ == '__main__':
main()
下面是读取日志,类似于linux的tail命令,输入today.log
作为参数
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import os
import time
def main():
fname = sys.argv[1]
with open("today.log") as f:
f.seek(0,2) #把指针置尾
while 1:
cursor = f.tell() #获取当前位置
line = f.readline()
# 判断是否读取数据
if line:
print line.strip()
else:
f.seek(cursor) # 将指针移动到本次循环的位置
if __name__ == '__main__':
main()
- seek(0, 2)是把指针放到末尾
- 先保存当前位置,如果读取出来的行是空的,先重置指针,等待下次的读取。
函数都有注释,它的实用意义非常大的,可能有些人会说为什么不用现成ELK,但往往实际上有很多限制,一个简单的脚本已经满足大部分的需求,在项目初期的时候有其重要的意义,到了项目后期比较有空的时候,可以做到更完善的,这就是Python脚本带来的好处。反过来想它的缺点就是这些东西到后期了,有些人不愿意动,因为好好地为什么要动呢,就算他功能已经越来越无法满足需要了,但却依然没有动力去改造,有风险也有时间成本。
3. 例2: 项目框架生成器
我记得大学的时候学了个php框架叫cakephp,类似ROR,当时惊为天人,这种自动生成的思想绝对是为懒人程序员准备的。后来到工作的时候,我发现有大量的代码是重复或者只需要改动一小部分就可以重用了。但缺点在哪里,如果我们写一个很灵活的函数用来适应各种情况,首先无法证明这个函数能在所有情况都能适应,如果需求改变了也有可能导致无法适应,如果每次持续的跟进有可能需要对这个函数进行大量的测试才能再次应用。
生成函数或者生成项目我认为尽量越简单越好,而不是生成非常复杂的项目函数。其次是定了一个项目框架,尽量把不变的写死,在编写业务的时候,越少变动就越不容易出错,这样可以把时间都放在重要的逻辑上。再是定了一些约定俗成的东西,在繁忙的业务过程中越是约定的多,越是不容易出错,最后当然是速度快了。Python代码再生成Python代码,这不是很酷的事情吗?把一些数据库缓存操作都生成好,只需要写业务逻辑,单元测试都省了80%。这样子的话,可能随手间就完成了一个业务。
这是一个文件模板,app.tpl,名字随便起的,扩展名无关,其中这里依赖了jinja2的库。{{author}}表示变量
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# author: {{author}}
下面是读取模板生成文件的脚本:
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from jinja2 import Template
import sys
def render_template(template, data):
with open(template) as f:
content = f.read()
content = content.decode("utf-8")
tpl = Template(content)
return tpl.render(data)
def main():
fname = sys.argv[1]
data = {"author": "Ryan"}
with open("author.py", "w") as f:
content = render_template("app.tpl", data)
f.write(content.encode("utf-8"))
if __name__ == '__main__':
main()
渲染完后生成的author.py文件。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# author: Ryan
另外,其实还有很多应用,例如,定时读取数据库数据,然后发按一定格式发邮件给运营和策划,这时候又可以用得上上面的模式。
4. 总结
文件读写在Python中已经简化了很多,所以用来快速处理数据是很适合的。生成项目模板这个例子在我这几年服务端编程工作运用得最多,有大量的代码是重复的,而我以前都用复制,然后一个一个改。但总是发现会改漏了部分变量,这时候想起了以前cakephp,不断地生成大量代码。生成的代码几乎很简单,易看易懂,因为都是采用同一个规律和习惯,这样子接手的人也容易上手,只需要去理解一下业务,几乎都不用看底层数据库和缓存函数。缺点就在于有代码量有点多。也可以使用例子2去监控一些数据,定时发邮件到你的邮箱里面,那么你就像个boss一样,掌控着一切,需要的时间其实只是一个下午而已。
后视镜 20191106
网友评论