Python语法速查: 12. 文件与输入输出,


返回目录

 

 (1)文件基本操作

● 文件常用操作

内置函数或方法描述
open(name [,mode [,buffering]]) 内置函数。用来打开文件,返回一个文件对象(file对象)。详见下述
f.close() file对象方法,关闭文件。
f.read() file对象方法,读取最多n个字节,若不指定n,则默认读取整个文件。读出的内容以字符串形式返回。
f.readline(size=-1) file对象方法。读取整行并返回一个字符串,若指定size,则本行最多读取size个字节。读出整行时返回字符串中含换行符。
f.readlines(hint=-1) file对象方法。读取所有行并返回一个列表,每行的字符串为一个列表元素,hint为最多读取的行数。(由于现在可以直接对文件对象进行迭代,故readlines()这个方法现在不怎么用了,详见下面文件迭代器说明。)
f.write(s) file对象方法。将给定字符串s写入文件。(若要换行,需要自己在s中加Python换行符)
f.writelines(lines) file对象方法。写入序列lines中的所有字符串。(换行同上)
f.tell() file对象方法。返回本文件对象在文件中的当前位置指针,返回值为整数。
f.seek(offset [,whence]) file对象方法。查找文件位置,详见下述
f.truncate(size=None) file对象方法。将文件截短为最多size字节。
f.flush() file对象方法。将输出缓冲区的内容强制写入磁盘并清空输出缓冲区。
f.fileno() file对象方法。返回一个整数文件描述符。
f.isatty() file对象方法。判断file对象是否为一个交互式终端,返回布尔值。

 

● file对象常用属性

属性说明
closed 布尔值,表示文件是否已关闭。
mode 字符串,文件的打开模式。详见下面open()函数的mode参数说明。
name 字符串,文件名
newlines 表示在文件中实际遇到的换行符表示,若还没遇到换行符,则为None。
encoding 字符串,表示文件编码。详见下面open()函数的encoding参数说明。

 

 

 

● open(name ,mode='r' ,buffering=-1, errors=None, newline=None, closefd=True, opener=None)

说明:

参数name:含完整路径的文件名

参数mode:见下表中的各个字符,可组合使用,如'rb'或'rw'等。

参数buffering:默认为-1,即缓冲区大小为本系统的磁盘块大小(常为4096字节),也可用其他大于1的数字指定缓冲区大小(字节数)。

参数encoding:文件的编码名称,如:'utf-8'、'ascii'、'cp936'等。

参数newline:控制通用换行符模式的行为,可设置为:'\n', '\r', '\r\n', '', None等。 如果设置为None,所有形式的换行符(如:'\n', '\r', '\r\n')都会被转换为'\n'。 如果设置为''(空字符串),则所有形式的换行都会被识别为换行符,但输入文本不会转换;

参数closefd:布尔值,控制在调用close()方法时,是否实际关闭底层的文件描述符,一般默认为True。

字符含义
r 读模式(默认)
w 写模式(首先会把文件现有内容全部清除,然后从头开始写)
x 若文件已存在,使用x模式会报错
a 追加写模式(从文件现有内容结尾处开始写)
b 二进制模式
t 文本模式(默认)
+ 读/写模式,可以跟'r'或'w'组合使用。'r+'表示可读写(但不清除现有内容);'w+'表示可读写(先清除所有内容)
 

关于“文本模式”和“二进制模式”的说明:

在Python3中,在文本模式下打开文件,读取操作将返回Unicode字符串;如果在二进制模式下打开文件,将返回字节字符串。

如果文件本身是二进制数据文件,由于read()方法的返回内容格式为字符串,故“文本模式”和“二进制模式”读取的内容看上去都像乱码,需要进一步的处理。

对于文本文件,用“文本模式”和“二进制模式”的效果差不多,唯一的不同是在“文本模式”下,Python会自动对文件中的换行符作一些转换。 在读取Windows格式的文本文件时,会将Windows形式的换行符'\r\n'转换成Python标准形式的换行符'\n'。 同样的,在写入Windows文本文件时,会将Python的换行符'\n'转换成Windows形式的'\r\n'写入文件。 在Linux平台不作任何转换。

 

返回索引

 

 

● seek(offset [,whence])

说明:

根据给定的offset和whence中的偏移规则,将本文件对象的当前位置指针移动到任意位置。offset为一个整数,whence表明offset的偏移起始位置,见下表: (若使用宏名称,需要import os模块

宏名称整数值说明
os.SEEK_SET 0 offset从文件头开始偏移。
os.SEEK_CUR 1 offset为从当前位置开始偏移。
os.SEEK_END 2 offset为从文件末尾开始偏移,此时offset通常为负数。
 

 

返回索引

 

 

● 确保文件被正常关闭的方法

方法一:使用 try / finally

f = open(filename)   # 打开文件
try:
    # …… 文件操作
finally:
    f.close()

 

方法二:使用 with 上下文管理器

with open(filename) as wf:   # with 打开文件后将其赋值到变量 wf 上
    do_somethin(wf)   
    
# 上面语句块结束后,文件被自动关闭,即使是异常引起的结束也是如此。

 

 

 

 (2)文件内容读出与文件迭代器

如果文件不是很大,传统的文件读出的操作是像下面这样子的(不使用文件迭代器)。

将文件内容一次性全部读出,每次处理一个字符:

f = open(filename)
for c in f.read():
    print(c)
f.close()

将文件所有的行一次性全部读出,每次处理一行:

f = open(filename)
for line in f.readlines():
    print(line)
f.close()

若文件很大,则可以每次仅读取一行:

f = openfile(filename)
while True:
    line = f.readline()
    if not line: break    # 当line返回空值时,表面已读到文件尾
    print(line)
f.close()

 

而现在,文件对象本身是支持迭代的。也就是说,对于很大的文件,不用一次性全部读出所有内容,用文件对象迭代器就可以在每次循环时只读出文件的一部分。

文件迭代器的用法:

f = open(filename)
for line in f:
    print(line)
f.close()

也可以让Python自己负责关闭文件:

for line in open(filename):
    print(line)

 

 

● 使用fileinput模块

使用fileinput模块也可以对文件进行迭代,fileinput模块还提供一些其他方法使能够更方便地对多个文件和多个输入输出流操作。

fileinput模块中的常用函数

函数说明
input(files=None, inplace=False, backup='', mode='r', openhook=None) 新建一个FileInput类的实例,用于对若干文件进行操作。files参数为文件名或输入流列表,若缺省则默认为sys.argv[1:]。若inplace参数为True,文件将原地处理,即:将文件内容复制到backup指定的文件,并将标准输出流重定向到本文件。
filename() 返回当前文件的名称。
fileno() 返回当前打开文件的文件描述符(整数),若未打开文件,则返回-1。
lineno() 返回当前累计的行数。即若处理多个文件,行数会累计。
filelineno() 返回当前文件当前行行号。
isfirstline() 刚才读入的行是否为文件的第一行。
isstdin() 最后读入的一行是否来自sys.stdin
nextfile() 关闭当前文件,移动到下一个文件。
close() 关闭序列。

 

用fileinput对文件进行迭代:

import fileinput
for line in fileinput.input(filename):
    print(line)

 

对目标文件的每行后面添加行号注释:

# test.py
import fileinput

for line in fileinput.input(inplace=True):    # files参数为空,默认使用sys.argv[1:]作为输入流列表
    line = line.rstrip()
    num = fileinput.lineno()
    print('%-40s # %2i' %(line, num))
    
# 运行:python test.py a.txt 后,会在a.txt文件的每一行后添加注释行号

 

 

 

 (3)输入与输出

Python解释器提供了3种标准文件对象:标准输入、标准输出、标准错误,分别在sys模块中表示为:sys.stdin, sys.stdout, sys.stderr。 通常,stdin被映射到接受用户键盘输入信息,而stdout和stderr在屏幕上生成文本。在某些情况下,集成开发环境(IDE)可能会更改sys.stdin, sys.stdout和sys.stderr。

文件的read()和write()也可以用于输出流和输入流,效果与print()和input()内置函数相同。

import sys
sys.stdout.write('Hello')     # 相当于:print('Hello')
a = sys.stdin.readline()      # 相当于:a = input() ,使用stdin在a中会有一个换行符。

Linux中的管道符号(|),将前一个命令的“标准输入”和后一个命令的“标准输出”连在一起,如果你的程序要读取管道中来的数据,只需使用读标准输入即可,如:

import sys
tx = sys.stdin.read()

 

● print()函数

print()函数可接收若干个要在屏幕上打印的参数,入参中间用逗号隔开,在屏幕上各个显示的入参之间以空格分隔。 若要将print()的内容重定向到一个文件,可以使用file=outfile关键字参数。若要更改默认的空格分隔,可使用sep=sepchar关键字参数。

print('Hello', 1, 2, 3)   # 输出显示为:Hello 1 2 3
print('Hello', 1, 2, 3, sep=',')    # 输出显示为:Hello,1,2,3
print('Hello', 1, 2, 3, file=f)     # 输出内容重定向到文件对象f

若要在输出文本中大量插入变量,可使用format()方法或string.Template方法,关于它们的用法 详见这里。

 

 

 

 (4)pickle与shelve模块

 

● pickle模块

pickle模块将对象序列化为一个字节流,这个字节流可以写入到文件并在以后从文件读出还原成对象。出于安全考虑,程序不应该处理来自不可信来源的文件来还原成对象。

序列化用户定义类的实例时,只会序列化数据,不会保存相应的类定义,序列化后的数据只包含相关类和模块的“名称”。且在还原一个实例时,不会调用其类方法__init__()。

pickle模块比较适合用于序列化:数字、字符串、元组、列表、只包含可序列化对象的字典、在模块顶层定义的用户定义类的实例。

pickle常用方法

函数说明
pickle.dump(obj, file, protocol=None) 将obj序列化并存储到“文件对象”file中。protocol可为:0、1、2、3、pickle.HIGHEST_PROTOCOL(自动选择最新协议)。若obj不支持序列号,则引发pickle.PicklingError异常
pickle.dumps(>obj, protocol=None) 与上面的dump()功能相同,只是不将序列化后的对象写入文件,而是将其作为一个bytes对象返回。
pickle.load(file) 从“文件对象”file中加载并还原一个序列化对象。如果该文件无法还原,则引发pickle.UnpicklingError异常;如果检测到文件尾,则引发EOFError异常。
pickle.loads(bytes_obj) 与上面load()功能相同,但不是从文件对象还原对象,而是从入参的bytes对象还原。

 

序列化对象和还原序列化示例:

# 序列化写入文件:
obj1 = SomeObject()
obj2 = SomeObject()
f = open(filename, 'wb')
pickle.dump(obj1, f)      # 先写入obj1
pickle.dump(obj2, f)      # 再写入obj2
f.close()

# 还原序列化对象:
f = open(filename, 'rb')
o1 = pickle.load(f)
o2 = pickle.load(f)
f.close()

 

 

● shelve模块

shelve模块是基于pickle模块建立的,但比pickle模块更加自动化。模块中的open()函数会创建一个Shelve对象,可以当做一个普通字典来使用(键名必须是字符串),在调用其sync()或close()方法后,其内容将被自动写入文件。

shelve使用示例:

import shelve
# 保存到文件:
s = shelve.open('test')    # shelve模块会自动添加扩展名.dat
s['a'] = [1,2,3]
s.close()                  # 保存内容到文件

# 从文件中读出:
s = shelve.open('test')
print(s['a'])
s['b'] = 'abc'             # 追加内容
del s['a']                 # 删除键'a'及其内容
s.sync()                   # 强制保存内容到文件
s.close()                  # close()会自动调用sync()方法而实现保存作用。

 

 

 

 (5)shutil模块

shutil模块用于执行高级的普通文件操作,例如:复制、移动、重命名等,但并不能处理管道、块设备等特殊文件。

函数说明
shutil.copy(src, dst) 将文件src复制到文件或目录下(若dst为目录,则复制到目录下;若dst为一文件名,则复制到dst同级目录下并重命名为指定文件名)。返回新复制的文件名(含路径)
shutil.copy2(src, dst) 与上面的copy()类似,但同时复制了最后访问时间和修改时间。
shutil.copytree(src, dst, symlinks=False, ignore=None) 递归地复制src下的整个目录树,创建目标目录dst(且不应该已存在),并使用copy2()复制每个文件。如果symlinks为True,则对于源目录树中的链接文件仅作为链接文件复制,否则复制真实文件到新目录树。 如果在复制过程中发生错误,则将收集错误,处理结束时提示Error异常,异常的参数是一份包含了所有错误的元组列表 (srcname, dstname, exception)。
shutil.move(src, dst) 将文件或目录从src移动到dst。如果src移动到了不同的文件系统中,将递归地复制src。
shutil.rmtree(path, ignore_errors=False, onerror=None) 删除整个目录树。如果ignore_errors为真,错误将被忽略;否则错误由onerror函数处理。
shutil.copymode(src, dst) 将文件的模式权限位(如:777)从src复制到dst
shutil.copystat(src, dst) 将权限位、最后访问时间、最后修改时间从src复制到dst。文件内容、拥有人等保持不变。
shutil.copyfile(src, dst) 将src的内容全部读出后,复制到dst。
shutil.copyfileobj(f1, f2 [,length]) 将打开的文件对象f1中的所有内容复制到打开的文件对象f2,length可指定最大缓冲容量,若位负数,则一次操作中复制全部数据。
shutil.ignore_pattern(*patterns) 创建一个函数,忽略所有patterns中给出的通配符样式模式。返回函数的主要用途是作为shutil.copytree()函数的ignore参数,也可给os.walk()函数使用。

 

 

 

 (6)os模块中的常用文件操作

● os模块

函数/属性说明
sep 属性。操作系统用于分隔路径各个部分的字符,在Linux上为'/',在Windows上为'\',在Mac上为':'
getcwd() 返回当前进程的工作路径字符串。
chdir(path) 将当前进程的工作目录修改为path。
listdir(path) 返回包含目录路径中各文件名和子目录名的列表(不包括'.'和'..'),不递归搜索。
mkdir(path [,mode]) 创建模式为mode的目录,默认模式为777。
makedirs(path [,mode]) 在创建目录时,会同时创建包含叶子目录所需要的中间级目录,若叶子目录已存在或者无法创建,将引发OSError异常。
rmdir(path) 删除目录,目录必须为空。
removedirs(path) 递归地目录删除函数,即在path描述链上的所有目录都将被删除。若其中某个目录不为空,则停止继续向上删除目录。
remove(path) 删除文件,同unlink()函数。
unlink(path) 删除文件,同remove()函数
rename(src, dst) 将文件或目录src重命名为dst
renames(old, new) 它会尝试创建新路径所需的中间目录,重命名完成之后,将使用removedirs()删除旧名称的目录链。

 

os.path模块

os.path模块以一种可移植的方式操作路径名称,可由os模块导入。

函数说明
文件与目录的路径操作
exists(path) 如果path指定的文件或目录存在,则返回True。若path是已损坏的符号链接,则返回False。
lexists(path) 功能同上,但只要链接文件存在,即便链接损坏也返回True。
isdir(path) 如果path是目录则返回True。
isfile(path) 如果path是文件则返回True。
islink(path) 如果path是符号链接则返回True。
ismount(path) 如果path是挂载点则返回True。
文件与目录的属性操作
getsize(path) 返回path的大小,以字节为单位
getatime(path) 返回最后一次访问path的时间,返回值是从纪元起始点开始的秒数。
getctime(path) 返回创建path的时间(Windows)或最后一次修改path的时间(Linux),返回值是从纪元起始点开始的秒数。
getmtime(path) 返回最后一次修改path的时间,返回值是从纪元起始点开始的秒数。
samefile(path1, path2) 如果path1和path2引用同一个文件或目录,返回True。
sameopenfile(fp1, fp2) 如果打开的文件对象fp1和fp2引用同一个文件,则返回True。
samestat(stat1, stat2) 如果fstat()、lstat()或stat()饭hi的stat对象stat1和stat2引用同一个文件,则返回True。
以下为纯路径字符串操作(不管实际目录或文件是否存在)
dirname(path) 返回path所在目录的名称。
basename(path) 返回path的基本名称(即不含父目录及以上路径)。
abspath(path) 返回path的绝对路径。
isabs(path) 如果path是绝对路径名称,则返回True。
normpath(path) 返回标准化路径名称。它将折叠多余分隔符,在Windows上,它把正斜杠转换为反斜杠。
normcase(path) 返回标准化路径名称并转换大小写,在不区分大小写的文件系统上,它把路径全转为小写字母,在Windows上,它把正斜杠转换为反斜杠。
join(path1 [,path2 [, ...]]) 将一个或多个路径组件智能连接为一个路径名称,例如:join('home', 'a', 'b')返回为 '/home/a/b'
split(path) 将path拆分为 (head, tail) 元组,tail为路径基本名称,head是tail之前的内容。相当于 (dirname(), basename())。
splitdrive(path) 将path拆分为 (driver, filename) 元组。在Windows上,drive是驱动器名,在Linux上,drive为空字符串。
splitext(path) 将path拆分为主文件名和后缀(扩展名),如 splittext('a.txt') 的返回值为 ('a', '.txt')
realpath(path) 返回path的真实路径,并除去路径中的所有符号链接(Linux)
relpath(path [,start]) 返回从当前工作目录到path的一条相对路径,可以提供start参数来指定另一个起始目录。
commonpath(list) 返回list中各个元素前缀路径相同的部分,如:os.path.commonpath(['/usr/lib', '/usr/local/lib']),返回:'/usr'
commonprefix(list) 返回list中各个元素前缀相同的部分,如:os.path.commonpath(['/usr/lib', '/usr/local/lib']),返回:'/usr/l'
expanduser(path) 将path中的用户主目录'~'替换成当前用户主目录的绝对路径名称。
expandvars(path) 将path中的'$name'或'${name}'替换成相应环境变量中的值。
其他
supports_unicode_filenames 变量,如果文件系统支持Unicode文件名,那么此变量为True。(一般Windows为True,Linux为False)

 

 

 

 

返回目录

 

 

 

相关内容

    暂无相关文章

评论关闭