文件是保存在计算机存储设备上的一些信息或数据。你已经知道了一些不同的文件类型,比如你的音乐文件,视频文件,文本文件。Linux 有一个思想是“一切皆文件”,这在实验最后的 lscpu 的实现中得到了体现。Python 给了你一些简单的方式操纵文件。

通常我们把文件分为两类,文本文件和二进制文件。文本文件是简单的文本,二进制文件包含了只有计算机可读的二进制数据。

文件操作

文件打开

我们使用 open() 函数打开文件。它需要两个参数,第一个参数是文件路径或文件名,第二个是文件的打开模式。模式通常是下面这样的:

  • "r",以只读模式打开,你只能读取文件但不能编辑/删除文件的任何内容
  • "w",以写入模式打开,如果文件存在将会删除里面的所有内容,然后打开这个文件进行写入
  • "a",以追加模式打开,写入到文件中的任何数据将自动添加到末尾

默认的模式为只读模式,也就是说如果你不提供任何模式,open() 函数将会以只读模式打开文件。

假设当前目录下已有sample.py文档,然后进入Python3打开这个文档:

>>> fobj = open("sample.txt")
>>> fobj
<_io.TextIOWrapper name='sample.txt' mode='r' encoding='UTF-8'>

文件关闭

打开文件后我们应该总是关闭文件。我们使用方法 close()完成这个操作。

>>> fobj.close()

始终确保你显式关闭每个打开的文件,一旦它的工作完成你没有任何理由保持打开文件。因为程序能打开的文件数量是有上限的。如果你超出了这个限制,没有任何可靠的方法恢复,因此程序可能会崩溃。

每个打开的文件关联的数据结构(文件描述符/句柄/文件锁...)都要消耗一些主存资源。因此如果许多打开的文件没用了你可以结束大量的内存浪费,并且文件打开时始终存在数据损坏或丢失的可能性。

文件读取

使用 read() 方法一次性读取整个文件。

>>> fobj = open("sample.txt")
>>> fobj.read()
'I love Python\nI love shiyanlou\n'
>>> fobj.close()

如果你再一次调用 read(),它会返回空字符串因为它已经读取完整个文件。

read(size) 有一个可选的参数 size,用于指定字符串长度。如果没有指定 size 或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。反之,会尽可能按比较大的 size 读取和返回数据。

readline() 能帮助你每次读取文件的一行。

>>> fobj = open("sample.txt")
>>> fobj.readline()
'I love Python\n'
>>> fobj.readline()
'I love shiyanlou\n'
>>> fobj.close()

使用 readlines() 方法读取所有行到一个列表中。

>>> fobj = open('sample.txt')
>>> fobj.readlines()
['I love Python\n', 'I love shiyanlou\n']
>>> fobj.close()

你可以循环遍历文件对象来读取文件中的每一行。

>>> fobj = open('sample.txt')
>>> for x in fobj:
... print(x, end = '')
...
I love Python
I love shiyanlou
>>> fobj.close()

让我们写一个程序,这个程序接受用户输入的字符串作为将要读取的文件的文件名,并且在屏幕上打印文件内容。

#!/usr/bin/env python3
name = input("Enter the file name: ")
fobj = open(name)
print(fobj.read())
fobj.close()

运行程序:

$ cd /home/shiyanlou
$ chmod +x test.py
$ ./test.py
Enter the file name: sample.txt
I love Python
I love shiyanlou

文件写入

让我们通过 write() 方法打开一个文件然后我们随便写入一些文本。

>>> fobj = open("ircnicks.txt", 'w')
>>> fobj.write('powerpork\n')
>>> fobj.write('indrag\n')
>>> fobj.write('mishti\n')
>>> fobj.write('sankarshan')
>>> fobj.close()

现在读取我们刚刚创建的文件:

>>> fobj = open('ircnicks.txt')
>>> s = fobj.read()
>>> fobj.close()
>>> print(s)
powerpork
indrag
mishti
sankarshan

文件操作示例程序

1、拷贝文件程序

在这个例子里我们拷贝给定的文本文件到另一个给定的文本文件。

#!/usr/bin/env python3
import sys
if len(sys.argv) < 3:
print("Wrong parameter")
print("./copyfile.py file1 file2")
sys.exit(1)
f1 = open(sys.argv[1])
s = f1.read()
f1.close()
f2 = open(sys.argv[2], 'w')
f2.write(s)
f2.close()

运行程序:

shiyanlou:~/ $ ./copyfile.py sample.txt sample2.txt
shiyanlou:~/ $ ll
总用量 20K
lrwxrwxrwx 1 shiyanlou shiyanlou 10 6月 9 2018 anaconda3 -> /anac
onda3
drwxrwxr-x 2 shiyanlou shiyanlou 4.0K 6月 9 2018 Code
-rwxrwxr-x 1 shiyanlou shiyanlou 239 2月 14 20:05 copyfile.py
drwxr-xr-x 2 shiyanlou shiyanlou 4.0K 6月 9 2018 Desktop
-rw-rw-r-- 1 shiyanlou shiyanlou 31 2月 14 20:06 sample2.txt
-rw-rw-r-- 1 shiyanlou shiyanlou 33 8月 8 2016 sample.txt

你可以看到我们在这里使用了一个新模块 syssys.argv包含所有命令行参数。这个程序的功能完全可以使用 shell 的 cp 命令替代:在 cp 后首先输入被拷贝的文件的文件名,然后输入新文件名。

sys.argv 的第一个值是命令自身的名字,下面这个程序打印命令行参数。

#!/usr/bin/env python3
import sys
print("First value", sys.argv[0])
print("All values")
for i, x in enumerate(sys.argv):
print(i, x)

运行程序:

$ ./argvtest.py Hi there
First value ./argvtest.py
All values
0 ./argvtest.py
1 Hi
2 there

这里我们用到了一个新函数 enumerate(iterableobject),在序列中循环时,索引位置和对应值可以使用它同时得到。

2、文本文件相关信息统计

让我们试着编写一个程序,对任意给定文本文件中的制表符、行、空格进行计数。

#!/usr/bin/env python3

import os
import sys def parse_file(path):
"""
分析给定文本文件,返回其空格、制表符、行的相关信息 :arg path: 要分析的文本文件的路径 :return: 包含空格数、制表符数、行数的元组
"""
fd = open(path)
i = 0
spaces = 0
tabs = 0
for i,line in enumerate(fd):
spaces += line.count(' ')
tabs += line.count('\t')
# 现在关闭打开的文件
fd.close() # 以元组形式返回结果
return spaces, tabs, i + 1 def main(path):
"""
函数用于打印文件分析结果 :arg path: 要分析的文本文件的路径
:return: 若文件存在则为 True,否则 False
"""
if os.path.exists(path):
spaces, tabs, lines = parse_file(path)
print("Spaces {}. tabs {}. lines {}".format(spaces, tabs, lines))
return True
else:
return False if __name__ == '__main__':
if len(sys.argv) > 1:
main(sys.argv[1])
else:
sys.exit(-1)
sys.exit(0)

你可以看到程序有两个函数,main() 和 parse_file() ,parse_file 函数真正的分析文件并返回结果,然后在 main() 函数里打印结果。

通过分割代码到一些更小的单元(函数)里,能帮助我们组织代码库并且也更容易为函数编写测试用例。

使用with语句

在实际情况中,我们应该尝试使用 with 语句处理文件对象,它会在文件用完后会自动关闭,就算发生异常也没关系。它是 try-finally 块的简写:

>>> with open('sample.txt') as fobj:
... for line in fobj:
... print(line, end = '')
...
I love Python
I love shiyanlou

综合示例——实现lscpu命令

在 Linux 下你可以使用 lscpu 命令来查看当前电脑的 CPU 相关信息,如下图:

实际上 lscpu 命令是读取 /proc/cpuinfo 这个文件的信息并美化输出,现在你可以自己写一个 Python 程序以只读模式读取 /proc/cpuinfo 这个文件,然后打印出来,这样你就有自己的一个 Python 版本的 lscpu 命令了 :)

记得一行一行的读取文本文件,不要一次性读取整个文件,因为有时候你读取的文件可能比可用内存还大。

参考链接:https://www.shiyanlou.com/courses/596

Python3简明教程(九)—— 文件处理的更多相关文章

  1. Python3 简明教程学习(上)

    一.开始 Python 之旅交互模式 1.Ctrl + D 输入一个 EOF 字符来退出解释器,也可以键入 exit() 来退出 2.#!/usr/bin/env python3 中#!称为 Sheb ...

  2. Python3 简明教程

    Python是由吉多·范罗苏姆(Guido Van Rossum)在90年代早期设计.它是如今最常用的编程 语言之一.它的语法简洁且优美,几乎就是可执行的伪代码. 注意:这篇教程是特别为Python3 ...

  3. Python3简明教程(十四)—— Collections模块

    collections 是 Python 内建的一个集合模块,提供了许多有用的集合类. 在这个实验我们会学习 Collections 模块.这个模块实现了一些很好的数据结构,它们能帮助你解决各种实际问 ...

  4. Python3简明教程(十二)—— 模块

    在这节我们将要学习 Python 模块相关知识.包括模块的概念和导入方法,包的概念和使用,第三方模块的介绍,命令行参数的使用等. 模块 到目前为止,我们在 Python 解释器中写的所有代码都在我们退 ...

  5. Python3简明教程(十一)—— 类

    本节中将通过定义一些简单的 Python 类,来学习 Python 面向对象编程的基本概念. 定义类 在写你的第一个类之前,你应该知道它的语法.我们以下面这种方式定义类: class nameofth ...

  6. Python3简明教程(十)—— 异常

    在本节我们学习 Python 的异常以及如何在你的代码中处理它们. 异常 在程序执行过程中发生的任何错误都是异常.每个异常显示一些相关的错误信息,比如你在 Python3 中使用 Python2 独有 ...

  7. Python3简明教程(六)—— 数据结构

    简单的来说,数据结构(data structure)是计算机中存储.组织数据的方式.比如我们之前使用过的列表就是一种数据结构,在这里我们还会深入学习它.之前也有简单的介绍. 列表 >>&g ...

  8. Python3简明教程(一)—— 开始Python之旅

    第一个Python程序 作为我们第一个Python程序——打印"Hello  World!". 在终端输入Python3进入交互界面: 输入print("Hello  W ...

  9. 实验楼-python3简明教程笔记

    #!/usr/bin/env python3 days = int(input("Enter days: ")) print("Months = {} Days = {} ...

随机推荐

  1. Ubuntu中字体的改变

    1.sudo dpkg-reconfigure console-setup 2.弹出 Configuring console-setup 界面,选择适当的编码格式,我们一般选择默认的UTF-8,选择O ...

  2. E20170405-gg

    repository n. 存储库,知识库 Permanent adj 永久的 host      n 主机,住处人,主人 authenticate v 使生效,验证 shell n 外壳 commi ...

  3. 关于js变量作用域

    先来看一段代码 var ss=1;function sss(){ alert(ss);}$(document).ready(function(){ var ss=2; alert(ss); sss() ...

  4. bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】

    第一问就是Σ(deg[u]-1)/2+1 第二问是二分,判断的时候考虑第一问的贪心规则,对于奇度数的点,两两配对之后一条延伸到上面:对于欧度数的点,两两配对或者deg[u]-2的点配对,然后一条断在这 ...

  5. 鸟哥私房菜基础篇:Linux 磁碟与档案系统管理习题

    猫宁!!! 参考链接:http://linux.vbird.org/linux_basic/0230filesystem.php 鸟哥是为中国信息技术发展做出巨大贡献的人. 1-我们常常说,开机的时候 ...

  6. PJzhang:贷款逾期与失信被执行人

    猫宁!!! 最近看到一家网贷机构在APP上的温馨提示,提到了网贷逾期与个人征信的关系以及向客户发放贷款的7项基本原则. 如下: 贷款申请及逾期告知 尊敬的客户,感谢您选择####股份有限公司为您提供贷 ...

  7. CIFAR10自定义网络实战

    目录 CIFAR10 MyDenseLayer CIFAR10 MyDenseLayer import os import tensorflow as tf from tensorflow.keras ...

  8. Ubuntu 18.04 LTS 安装后 各种问题以及解决方案

    1. root的初始密码,默认是不知道的,需要进行设置 a. 进入终端自己的用户 b. 输入 sudo passwd回车 c. 输入新密码,回车,重复,回车,搞定 d. su 一下,就可以了 2.  ...

  9. 51Nod 1095 Anigram单词

    熟练使用map即可,不然用vector会超时 #include <iostream> #include <cstring> #include <string> #i ...

  10. zabbix被动模式和主动模式

    1 被动模式 zabbix默认采用被动模式.就是agent等待server采集数据. 在items中,type为zabbix agent就是指被动模式. 流程为:agent周期性收集数据,server ...