06 . Python3入门之IO编程(文件操作)
IO编程简介
IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。
比如你打开浏览器,访问新浪首页,浏览器这个程序就需要通过网络IO获取新浪的网页。浏览器首先会发送数据给新浪服务器,告诉它我想要首页的HTML,这个动作是往外发数据,叫Output,随后新浪服务器把网页发过来,这个动作是从外面接收数据,叫Input。所以,通常,程序完成IO操作会有Input和Output两个数据流。当然也有只用一个的情况,比如,从磁盘读取文件到内存,就只有Input操作,反过来,把数据写到磁盘文件里,就只是一个Output操作。
IO编程中,Stream(流)是一个很重要的概念,可以把流想象成一个水管,数据就是水管里的水,但是只能单向流动。Input Stream就是数据从外面(磁盘、网络)流进内存,Output Stream就是数据从内存流到外面去。对于浏览网页来说,浏览器和新浪服务器之间至少需要建立两根水管,才可以既能发数据,又能收数据。
由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,就存在速度严重不匹配的问题。举个例子来说,比如要把100M的数据写入磁盘,CPU输出100M的数据只需要0.01秒,可是磁盘要接收这100M数据可能需要10秒,怎么办呢?有两种办法:
第一种是CPU等着,也就是程序暂停执行后续代码,等100M的数据在10秒后写入磁盘,再接着往下执行,这种模式称为同步IO;
另一种方法是CPU不等待,只是告诉磁盘,“您老慢慢写,不着急,我接着干别的事去了”,于是,后续代码可以立刻接着执行,这种模式称为异步IO。
同步和异步的区别?
是否等待IO执行的结果。好比你去麦当劳点餐,你说“来个汉堡”,服务员告诉你,对不起,汉堡要现做,需要等5分钟,于是你站在收银台前面等了5分钟,拿到汉堡再去逛商场,这是同步IO。
你说“来个汉堡”,服务员告诉你,汉堡需要等5分钟,你可以先去逛商场,等做好了,我们再通知你,这样你可以立刻去干别的事情(逛商场),这是异步IO。
很明显,使用异步IO来编写程序性能会远远高于同步IO,但是异步IO的缺点是编程模型复杂。想想看,你得知道什么时候通知你“汉堡做好了”,而通知你的方法也各不相同。如果是服务员跑过来找到你,这是回调模式,如果服务员发短信通知你,你就得不停地检查手机,这是轮询模式。总之,异步IO的复杂度远远高于同步IO。
操作IO的能力都是由操作系统提供的,每一种编程语言都会把操作系统提供的低级C接口封装起来方便使用,Python也不例外。我们后面会详细讨论Python的IO编程接口。
输出格式美化
# Python有两种输出值的方式,表达式语句和print()函数
# 第三种方式是使用文件对象的write()方法,标准输出文件可以用sys.stdout引用
# 如果你希望输出的形式更加多样,可以使用str.format()函数格式化输出值
# 如果你希望输出值都转换成字符串,可以使用repr()或str()函数实现
# str: 函数返回一个用户易读的表达形式
# repr(): 产生一个解释器易读的表达形式
例如
# 简单应用
name = '幽梦'
age = 18
sex = '男'
msg = F'姓名: {name}, 性别: {age} , 年龄: {sex}' # 大写字母也可以
print(msg)
# 任意表达式
print(f'{3*21}')
name = 'flying'
print(f'全部大写: {name.upper()}')
# 字典也可以
teacher = {'name':'幽梦','age':18}
msg = f"The student is {['name']}, age{teacher['age']}"
print(msg) # The comedian is 太白金星, aged 18
# 列表也行
li1 = ['幽梦',18]
msg = f'姓名:{li1[0]},年龄:{li1[1]}.'
print(msg)
# 也可以插入表达式
def sum_a_b(a,b):
return a + b
a = 1
b = 2
print('求和的结果为' + f'{sum_a_b(a,b)}')
# 多行f
name = 'youmen'
age = 18
sex = '男'
speaker = f'Hi {name}.'\
f'You are {age} years old.'\
f'You are a {sex} guy!'
print(speaker)
str.format()的基本使用如下
print('{}网址: "{}!"'.format('菜鸟教程','www.YouMen.com'))
菜鸟教程网址: "www.YouMen.com!"
# 括号及其里面的字符(称作格式化字段)将被format()中的参数替换.
# 在括号中的数字用于指向传入对象在format()中的位置,如下所示:
>>> print('{0}和{1}'.format('Google','baidu'))
Google和baidu
# 如果在format()中使用了关键字参数,那么他们的值会指向使用该名字的参数.
print('站点列表{0},{1},和{other}'.format('Google','baidu.com',other='TaoBao'))
站点列表Google,baidu.com,和TaoBao
>>> import math
>>> print('常亮p1的值近似为: {}.'.format(math.pi))
常亮p1的值近似为: 3.141592653589793.
# 可选项:和格式标识符可以跟着字段名,这就允许对值进行更好的格式化,下面例子将Pi保留到小数后三位.
>>> print('常亮PI的值近似为{0:.3f}。'.format(math.pi))
常亮PI的值近似为3.142。
# 在:后传入一个整数,可以保证该域至少有那么多的宽度,对于美化表格很有用
>>> table={'Google':1,'YouMen':2,'Baidu':3}
>>> for name, number in table.items():
... print('{0:10} ==> {1:10d}'.format(name, number))
...
Google ==> 1
YouMen ==> 2
Baidu ==> 3
# 如果你有一个很长的格式化字符串,而你不想将他们分开,那么在格式化时通过变量名而非位置会是很好的事情.
# 最简单的就是传入一个字典,然后使用方括号[]来访问键值.
>>> table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
>>> print('Runoob: {0[Runoob]:d}; Google: {0[Google]:d}; Taobao: {0[Taobao]:d}'.format(table))
Runoob: 2; Google: 1; Taobao: 3
旧式字符串格式化
- %操作符也可以实现字符串格式化,他将左边的参数作为sprintf()式的格式化字符串,而将右边的代入,然后返回格式化的字符串,例如:
import math
print('常量PI的值近似为: %5.3f。'%math.pi)
常量PI的值近似为: 3.142。
读取键盘输入
Python提供了input内置函数从标准输入读入一行文本,默认的标准输入是键盘.
input可以接受一个Python表达式作为输入,并将运算结果返回.
str = input("请输入:")
print("你输入的内容是:",str)
请输入:
zhou
文件读写
读写文件是最常见的IO操作,Python内置了读写文件的函数,用法和C是兼容的.
读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。
open()将会返回一个file对象,基本语法格式如下
open(filename,mode)
filename: 包含了你要访问的文件名称的字符串值
mode: 决定了打开文件的模式: 只读,写入,追加等,所有可取值见如下的完全列表,这个参数是非强制的,默认文件的访问模式为只读(r)
不同模式打开文件的完全列表:
模式 | 描述 |
---|---|
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
下图很好的总结了这几种模式:
模式 | r | r+ | w | w+ | a | a+ |
---|---|---|---|---|---|---|
读 | + | + | + | + | ||
写 | + | + | + | + | + | |
创建 | + | + | + | + | ||
覆盖 | + | + | ||||
指针在开始 | + | + | + | + | ||
指针在结尾 | + | + |
Open()方法
Python open() 方法用于打开一个文件,并返回文件对象,在对文件进行处理过程都需要使用到这个函数,如果该文件无法被打开,会抛出 OSError。或者文件不存在抛出IOError错误.
注意: 使用open()方法一定要保证关闭文件对象,即调用close()方法
Open()函数常用形式是接受两个参数: 文件名(file)和模式(mode)
如果文件打开成功,接下来,调用read()方法可以一次读取文件的全部内容,Python把内容读到内存,用一个str对象表示。
open(file,mode='r')
# 完整语法格式为:
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
参数说明:
* file: 必需,文件路径(相对或者绝对路径)。
* mode: 可选,文件打开模式
* buffering: 设置缓冲
* encoding: 一般使用utf8
* errors: 报错级别
* newline: 区分换行符
* closefd: 传入的file参数类型
* opener:
mode参数有:
模式 | 描述 |
---|---|
t | 文本模式 (默认)。 |
x | 写模式,新建一个文件,如果该文件已存在则会报错。 |
b | 二进制模式。 |
+ | 打开一个文件进行更新(可读可写)。 |
U | 通用换行模式(Python 3 不支持)。 |
r | 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。 |
rb | 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。 |
r+ | 打开一个文件用于读写。文件指针将会放在文件的开头。 |
rb+ | 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。 |
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。 |
a | 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
ab | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。 |
a+ | 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。 |
ab+ | 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。 |
默认为文本模式,如果要以二进制模式打开,加上b
以下实例将字符串写入到文件foo.txt中:
# 打开一个文件
f = open("test.txt","w",encoding="utf-8")
f.write("hello world! \n 世界你好!")
# 关闭打开的文件
f.close
cat test.txt
hello world!
世界你好!
# 在实际编程中,我们经常忘记关闭已经打开的文件对象,这样就会导致系统资源的浪费。
# 使用 with 语句来管理上下文操作之后,python内部会自动关闭并释放文件资源。
# 操作只需要为文件句柄起个别名为f,下面直接使用即可
# 打开一个文件
with open('test.txt','w',encoding="utf-8") as you:
li = ['hello\n','world\n']
you.writelines(li)
print("结束")
cat test.txt
hello
world
文件对象的方法
1. f.read()
为了读取一个文件的内容,调用 f.read(size), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。
size 是一个可选的数字类型的参数。 当 size 被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。
以下实例假定文件 test.txt 已存在(上面实例中已创建)
f = open("test.txt","r")
str = f.read()
print(str)
f.close()
hello
world
2. f.readline()
f.readline()会从文件中读取单独的一行,换行符为'\n',f.readline()如果返回一个空字符串,说明已经读取到最后一行.
f = open("test.txt","r")
str = f.readline()
print(str)
f.close()
hello
3. f.readlines()
f.readlines()将返回该文件中包含的所有行
如果设置可选参数sizehint,则读取指定长度的字节,并且将这些字节按行分割.
f = open("test.txt","r")
str = f.readlines()
print(str)
f.close()
['hello\n', 'world\n']
另一种方法就是迭代一个文件对象然后读取每行
for line in f:
print(line,end='')
f.close()
hello
world
# 这个方法很简单, 但是并没有提供一个很好的控制。 因为两者的处理机制不同, 最好不要混用。
4. f.write()
f.write(string)将string写入到文件中,然后返回写入的字符数.
f = open("test.txt","w",encoding="utf-8")
str1 = ("www.youmen.com",100)
s = str(str1)
# 如果不是字符串类型,需要先将其转换一下,否则执行报错.
num = f.write(s)
print(num)
f.close()
23
# f.tell()
# f.tell()返回文件对象当前所处的位置,他是从文件开头开始算起的字节数
5. f.seek()
# 如果要改变文件当前的位置, 可以使用 f.seek(offset, from_what) 函数。
# from_what 的值, 如果是 0 表示开头, 如果是 1 表示当前位置, 2 表示文件的结尾,例如:
# seek(x,0) : 从起始位置即文件首行首字符开始移动 x 个字符
# seek(x,1) : 表示从当前位置往后移动x个字符
# seek(-x,2):表示从文件的结尾往前移动x个字符
# from_what 值为默认为0,即文件开头。下面给出一个完整的例子:
>>> f = open('/tmp/foo.txt', 'rb+')
>>> f.write(b'0123456789abcdef')
16
>>> f.seek(5) # 移动到文件的第六个字节
5
>>> f.read(1)
b'5'
>>> f.seek(-3, 2) # 移动到文件的倒数第三字节
13
>>> f.read(1)
b'd'
6. f.close()
# 在文本文件中(那些打开文件的模式是没有b的),只会相对于文件起始位置进行定位.
# 当你处理一个文件后,调用f.close()来关闭文件并释放系统的资源,如果尝试在调用该文件,则会抛出异常.
# 所以当处理文件对象时,使用with关键字是非常好的方式,结束后,会帮你正确的关闭文件,写起来比try - finally语句块要简短
>>> with open('/tmp/foo.txt', 'r') as f:
... read_data = f.read()
>>> f.closed
True
7. pickle模块
# Python的pickle模块实现了基本的数据序列和反序列化
# 通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储
# 通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象
# 基本接口
pickle.dump(obj, file, [,protocol])
# 有了pickle这个对象,就能对file以读取的形式打开:
x = pickle.load(file)
# 从file中读取一个字符串,并将它重构成原来的python对象.
# file: 类文件对象,有read()和readline()接口
StringIO
很多时候,数据读写不一定是文件,也可以是内存中读写.StringIO顾名思义就是内存中读写str,要把str写入StringIO,我们需要先创建一个StringIO,然后像文件一样写入即可:
Example1
Example2
import os
with open('a.txt', 'r', encoding='utf-8') as read_f, open(
'.a.txt.swap','w', encoding='utf-8') as write_f:
r_data=read_f.read() # 全部读入内存,如果文件很大,会很卡
w_data=r_data.replace('world','python') # 在内存中完成修改
write_f.write(w_data) # 一次性写入新文件
os.remove('a.txt')
os.rename('.a.txt.swap','a.txt')
file对象
file 对象使用 open 函数来创建,下表列出了 file 对象常用的函数:
序号 | 方法及描述 |
---|---|
1 | file.close()关闭文件。关闭后文件不能再进行读写操作。 |
2 | file.flush()刷新文件内部缓冲,直接把内部缓冲区的数据立刻写入文件, 而不是被动的等待输出缓冲区写入。 |
3 | file.fileno()返回一个整型的文件描述符(file descriptor FD 整型), 可以用在如os模块的read方法等一些底层操作上。 |
4 | file.isatty()如果文件连接到一个终端设备返回 True,否则返回 False。 |
5 | file.next()Python 3 中的 File 对象不支持 next() 方法。返回文件下一行。 |
6 | file.read([size])从文件读取指定的字节数,如果未给定或为负则读取所有。 |
7 | file.readline([size])读取整行,包括 "\n" 字符。 |
8 | file.readlines([sizeint])读取所有行并返回列表,若给定sizeint>0,返回总和大约为sizeint字节的行, 实际读取值可能比 sizeint 较大, 因为需要填充缓冲区。 |
9 | file.seek(offset[, whence])移动文件读取指针到指定位置 |
10 | file.tell()返回文件当前位置。 |
11 | file.truncate([size])从文件的首行首字符开始截断,截断文件为 size 个字符,无 size 表示从当前位置截断;截断之后后面的所有字符被删除,其中 Widnows 系统下的换行代表2个字符大小。 |
12 | file.write(str)将字符串写入文件,返回的是写入的字符长度。 |
13 | file.writelines(sequence)向文件写入一个序列字符串列表,如果需要换行则要自己加入每行的换行符。 |
06 . Python3入门之IO编程(文件操作)的更多相关文章
- Linux C高级编程——文件操作之系统调用
Linux C高级编程文件操作之系统调用 宗旨:技术的学习是有限的,分享的精神是无限的. 库函数是一些完毕特定功能的函数.一般由某个标准组织制作公布,并形成一定的标准.使用库函数编 ...
- Python3 IO编程之操作文件和目录
如果我们要操作文件,目录,可以在命令行下面输入操作系统提供的各种命令来完成.比如ls,cp等命令 如果要在python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令指示简单地调用了操作系 ...
- Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化
IO编程 IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口.从 ...
- IO编程、操作文件或目录、序列化、JSON
IO中指Input/Output,即输入和输出:涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口 1.由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,存在速度严重不匹配问题.eg ...
- Python学习(九)IO 编程 —— 文件夹及文件操作
Python 文件夹及文件操作 我们经常会与文件和目录打交道,对于这些操作,python可以使用 os 及 shutill 模块,其中包含了很多操作文件和目录的函数. os 可以执行简单的文件夹及文件 ...
- java中io对文件操作的简单介绍
11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...
- Linux系统编程@文件操作(一)
只总结了部分常用的内容,详细内容参考<UNIX环境高级编程>及相关书籍. Linux中文件编程可以使用两种方法 Linux系统调用(依赖于系统) C语言库函数(不依赖于系统) Linux系 ...
- Java IO编程——文件拷贝
在操作系统里面有一个copy命令,这个命令的主要功能是可以实现文件的拷贝处理,现在要求模拟这个命令,通过初始化参数输入拷贝的源文件路径与拷贝的目标路径实现文件的拷贝处理. 需求分析: ·需要实现文件的 ...
- python3.0 第三天 文件操作
文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 Somehow, it seems the love I knew was alway ...
随机推荐
- centos安装libconfig
安装很简单,生成的.so文件会被安装到/usr/local/lib目录,记得修改/etc/profile. 安装过程会出现两个错误: What is makeinfo, and how do I ge ...
- 动态代理学习(二)JDK动态代理源码分析
上篇文章我们学习了如何自己实现一个动态代理,这篇文章我们从源码角度来分析下JDK的动态代理 先看一个Demo: public class MyInvocationHandler implements ...
- csu1617]强连通分量
题意:定义域属于一个集合S={0,1,...,n-1},求S的子集个数,满足以子集的元素为定义域的函数P(x)的值域等于子集本身. 思路:以元素为点,x到P(x)连一条有向边,不难发现,如果有一个有向 ...
- [csu1603]贪心
题意:有n门考试,对于考试i,不复习它能考si分,复习它的每小时能提高ai分,每过一小时ai会减小di,也就是说,连续复习某门科目每小时提高的分为ai, ai-di, ai-2di...,但每门考试最 ...
- 浅谈字典树Trie
\(\;\) 本文是作者学习<算法竞赛进阶指南>的所得,有些语言是摘自其中. \(\;\) 基础知识 定义 \(\;\) 字典树(Trie):是一种支持字符串查询的多叉树结构.其中的每个节 ...
- Python --表达式和运算符
表达式 由一个或者几个数字或者变量和运算符组合成的一行代码 通常会返回一个结果 运算符 由一个以上的值经过变化得到新值的过程就叫做运算 用于运算的符号称为运算符 运算符的分类: 算数运算符 比较或者关 ...
- nginx均衡负载
一直在担心session 问题,结果试了2个web 论坛,discuz 和phpbb ,前面用nginx 均衡负载,后端是apache httpd +php ,mysql 用同一个,修改一下confi ...
- clickhouse入门到实战及面试
第一章. clickhouse入门 一.ClickHouse介绍 ClickHouse(开源)是一个面向列的数据库管理系统(DBMS),用于在线分析处理查询(OLAP). 关键词:开源.面向列.联机分 ...
- java十大排序
0.1 算法分类 十种常见排序算法可以分为两大类: 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序. 非比较类排序:不通过比较来决 ...
- DPDK开发环境搭建(学会了步骤适合各版本)
一.版本的选择 首先要说明的是,对于生产来说DPDK版本不是越高越好,如何选择合适的版本? 1.要选择长期支持的版本LTS(Long Term Support) 2.根据当前开发的系统环境选择 可以在 ...