文件是保存在计算机存储设备上的一些信息或数据。你已经知道了一些不同的文件类型,比如你的音乐文件,视频文件,文本文件。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. ES6之Object

    对象属性模型的相关方法: 对象自身所有属性名称 Object.getOwnPropertyNames(obj)              //[] 获取某个属性的attribute对象 Object. ...

  2. node --save可以省略掉手动修改package.json的步骤

    当你为你的模块安装一个依赖模块时,正常情况下你得先安装他们(在模块根目录下npm install module-name),然后连同版本号手动将他们添加到模块配置文件package.json中的依赖里 ...

  3. 3dmath复习随笔

    左手坐标系与右手坐标系 旋转正方向,下图是右手系,左手系同理 向量 点乘: 叉乘: dx是左手系,使用行向量,vABC,乘矩阵用左乘 opengl是右手系,使用列向量,CBAv,乘矩阵用右乘 u3d貌 ...

  4. Ironpython 安装numpy包

    http://pytools.codeplex.com/wikipage?title=NumPy%20and%20SciPy%20for%20.Net https://www.enthought.co ...

  5. jzoj5980. 【WC2019模拟12.27】字符串游戏

    首先发现双方可以有一个默契,不管谁刻意,都可以把串变为诸如\(...101010101...\)的形式 所以先手要赢的话就是要在上面的基础之上加一个字符使其变为要求的子串 那么就是要求的子串中相邻两个 ...

  6. 高级开发不得不懂的Redis Cluster数据分片机制

    Redis 集群简介 Redis Cluster 是 Redis 的分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 分布式方面的需求. Redis Cluster 一般由多个节点组 ...

  7. Item

    抓取的主要目标是从非结构化源(通常是网页)中提取结构化数据 ScrapySpider可以以python字典的形式返回提取的数据,这很方便和熟悉 但python dicts缺乏结构,很容易在字段名中输入 ...

  8. Python基础知识(2)

    1:if比较运算符.and.or >=:大于或者等于 <=:小于或者等于 ==:等于 !=:不等于  (<>:也是不等于,在Python2中可用.Python3中无法使用) a ...

  9. nginx使用autoindex

    有时候一个nginx服务就是为了用来下载文件的,网上很多下载服务都是这样的 这个很简单 在http段加上以下参数,重启nginx就行. autoindex on; autoindex_exact_si ...

  10. Caffe实战四(Caffe可视化方法)

    面对一堆文件,一行行的数据,确实很难理解深度学习相关的概念,好比训练的数据.构建的网络是怎样的?今天按照书中第16天的内容实践了一翻,终于看到了所谓的深度神经网络的模样.(参考:<深度学习 21 ...