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编程(文件操作)的更多相关文章

  1. Linux C高级编程——文件操作之系统调用

    Linux C高级编程文件操作之系统调用 宗旨:技术的学习是有限的,分享的精神是无限的.           库函数是一些完毕特定功能的函数.一般由某个标准组织制作公布,并形成一定的标准.使用库函数编 ...

  2. Python3 IO编程之操作文件和目录

    如果我们要操作文件,目录,可以在命令行下面输入操作系统提供的各种命令来完成.比如ls,cp等命令 如果要在python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令指示简单地调用了操作系 ...

  3. Python之IO编程——文件读写、StringIO/BytesIO、操作文件和目录、序列化

    IO编程 IO在计算机中指Input/Output,也就是输入和输出.由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口.从 ...

  4. IO编程、操作文件或目录、序列化、JSON

    IO中指Input/Output,即输入和输出:涉及到数据交换的地方,通常是磁盘.网络等,就需要IO接口 1.由于CPU和内存的速度远远高于外设的速度,所以,在IO编程中,存在速度严重不匹配问题.eg ...

  5. Python学习(九)IO 编程 —— 文件夹及文件操作

    Python 文件夹及文件操作 我们经常会与文件和目录打交道,对于这些操作,python可以使用 os 及 shutill 模块,其中包含了很多操作文件和目录的函数. os 可以执行简单的文件夹及文件 ...

  6. java中io对文件操作的简单介绍

    11.3 I/O类使用 由于在IO操作中,需要使用的数据源有很多,作为一个IO技术的初学者,从读写文件开始学习IO技术是一个比较好的选择.因为文件是一种常见的数据源,而且读写文件也是程序员进行IO编程 ...

  7. Linux系统编程@文件操作(一)

    只总结了部分常用的内容,详细内容参考<UNIX环境高级编程>及相关书籍. Linux中文件编程可以使用两种方法 Linux系统调用(依赖于系统) C语言库函数(不依赖于系统) Linux系 ...

  8. Java IO编程——文件拷贝

    在操作系统里面有一个copy命令,这个命令的主要功能是可以实现文件的拷贝处理,现在要求模拟这个命令,通过初始化参数输入拷贝的源文件路径与拷贝的目标路径实现文件的拷贝处理. 需求分析: ·需要实现文件的 ...

  9. python3.0 第三天 文件操作

    文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 Somehow, it seems the love I knew was alway ...

随机推荐

  1. 前端——localStorage详细总结

    一.localStorage简介: 在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cooki ...

  2. Spring官网阅读(十八)Spring中的AOP

    文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...

  3. 解密C语言编译背后的过程

    我们大部分程序员可能都是从C语言学起的,写过几万行.几十万行.甚至上百万行的代码,但是大家是否都清楚C语言编译的完整过程呢,如果不清楚的话,我今天就带着大家一起来做个解密吧. C语言相对于汇编语言是一 ...

  4. 【Scala】用实例弄清楚scala几种函数的定义和特点

    文章目录 作为参数的函数 匿名函数 柯里化函数(currying) 闭包函数 作为参数的函数 scala> val a1 = Array(1,2,3,4) //这是一个数组 a1: Array[ ...

  5. Day_08【面向对象】扩展案例4_年龄为30岁的老王养了一只黑颜色的2岁的宠物……

    #分析以下需求,并用代码实现: 1.定义动物类 属性: 年龄,颜色 行为: eat(String something)方法(无具体行为,不同动物吃的方式和东西不一样,something表示吃的东西) ...

  6. Hexo+GitHub Actions 完美打造个人博客

    Hexo简介 Hexo是一款基于Node.js的静态博客框架,依赖少易于安装使用,可以方便的生成静态网页托管在GitHub和Coding上,是搭建博客的首选框架.大家可以进入hexo官网进行详细查看, ...

  7. vue-cli3.0读取外部化配置文件来修改公共路径

    之前我写过一篇通过nginx配置代理转发的博客,正常来说也是正确的,但不足之处在了甲方还用了F5负载均衡和gateway来代理转发.所以之前我认为的请求->nginx转发代理->后端服务, ...

  8. GAN的前身——VAE模型原理

    GAN的前身——VAE模型 今天跟大家说一说VAE模型相关的原理,首先我们从判别模型和生成模型定义开始说起: 判别式模型:已知观察变量X和隐含变量z,它对p(z|X)进行建模,它根据输入的观察变量X得 ...

  9. uCOS2014.1.11

    typedef unsigned char  BOOLEAN;typedef unsigned char  INT8U;      /* Unsigned  8 bit quantity   */ty ...

  10. 设计模式之GOF23装饰模式

    装饰模式decorator 作用: -动态的为一个对象增加新功能 -装饰模式是一种用于代替继承的技术,无需通过增加子类就能扩展对象的新功能,适用对象的组合关系代替继承关系,更加灵活,同时避免类型体系的 ...