“专业人士笔记”系列目录:创帆云:Python成为专业人士笔记--强烈建议收藏!每日持续更新!zhuanlan.zhihu.com
文件操作介绍
在存储,读取或传输数据时,对操作系统的文件进行读写是经常涉及到的场景。与其他语言不同,Python大大简化了读取/写入和关闭文件的过程,最少2行代码就可完成上述所有操作;本文说明了Python如何与操作系统上的文件进行交互。
文件模式
可以使用mode参数指定的不同模式打开文件,这些包括 :
‘r’ – 只读模式。默认值。它只允许您读取文件,而不允许您修改它。当使用此模式时,文件必须存在。
‘w’ – 写入模式。 如果它不存在 ,将创建一个新文件,否则将覆盖文件,并允许您写入它。
‘a’ – 追加模式。它将把数据写到文件的末尾。它不会擦除文件,并且在这种模式下,文件必须已经存在。
‘rb’ – 二进制读模式。这类似于r,除了读取是在二进制模式下强制执行的。
‘r+’ – 读写模式。这允许您同时读写文件,而不必使用r和w ,但前提是文件必须已存在
‘rb+’ – 二进制读写模式。和r+一样,只是数据是二进制的
‘wb’ – 二进制写入模式。和w一样,只是数据是二进制的。
‘w+’ – 读写模式,功能与r+相同,但如果文件不存在,则创建一个新文件。否则,文件将被覆盖
‘wb+’ – 二进制模式下的读写模式。和w+一样,但是数据是二进制的。
‘ab’ – 以二进制模式附加。类似于a,只是数据是二进制的。
‘a+’ – 附加和读取模式。类似于w+,因为如果文件不存在,它将创建一个新文件 , 如果文件存在,则文件指针位于文件的末尾。
‘ab+’ – 二进制附加和读取模式。与a+相同,只是数据是二进制的。
Python 3添加了一个新的模式来进行独占创建,这样您就不会意外地截断或覆盖现有文件。
‘x’ – 以独占模式打开,如果文件已经存在,将引发FileExistsError
‘xb’ – 同x模式,只是数据是二进制
‘x+’ – 读写模式。类似于w+,因为如果文件不存在,它将创建一个新文件。否则
将产生 FileExistsError.
‘xb+’ – 和x+完全一样,数据是二进制的
符合python风格的文件操作代码结构:
try:
with open("fname", "r") as fout:
# 这里写打开文件后的处理逻辑
except FileExistsError:
# 文件异常处理代码
逐行读取文件
逐行遍历文件的最简单方法 :
#创建测试文件(当前项目路径下)
with open('myfile.txt', 'w') as fp:
fp.write('我\n爱\n你')
#逐行读取
with open('myfile.txt', 'r') as fp:
for line in fp:
print(line)
#输出:
我
爱
你
readline()允许对逐行迭代进行更细粒度的控制。下面的例子等价于上面的例子 :
#创建测试文件(当前项目路径下)
with open('myfile.txt', 'w') as fp:
fp.write('我\n爱\n你')
#逐行读取
with open('myfile.txt', 'r') as fp:
content='';
while True:
content=fp.readline();
print(content)
if(content==''):
#如果读到空字符串,证明结束并返回
break;
#输出:
我
爱
你
但是,不建议将for循环迭代器和readline()一起使用
如何更精细的控制行读取,更常见的是,用readlines()函数存储文件行的可迭代集合 :
#创建测试文件(当前项目路径下)
with open('myfile.txt', 'w') as fp:
fp.write('我\n爱\n你')
#逐行读取
with open("myfile.txt", "r") as fp:
lines = fp.readlines()
#查询
for i in range(len(lines)):
print("Line " + str(i) + ": " + lines[i])
#输出:
Line 0: 我
Line 1: 爱
Line 2: 你
遍历文件(递归)
要迭代所有文件,包括子目录中的文件,请使用os.walk :
import os
for root, folders, files in os.walk('.'): #该路径为云环境上项目路径,可以替换成其它路径甚至根路径'/'
# 获取所有文件夹
for file in folders:
print(root,file)
#获取所有文件
for filename in files:
print(root, filename)
#输出:
. aaa
. hello.py
. test.py
. test2.py
. test3233
. main.py
. shoppinglist.txt
. myfile.txt
在python3中,如果你希望快速获取文件对象,您可以使用更有效的方法os.scandir,像这样:
import os
for entry in os.scandir('.'):
if not entry.name.startswith('.') and entry.is_file():
print(entry)
#输出:
#当然,可以直接用print(entry.name)输出它们的文件名
获取文件完整内容
文件I / O的首选方法是使用with关键字;这样可以确保一旦阅读或写作完成后,python能够帮你处理剩余的文件关闭、资源清理等工作
#创建测试文件(当前项目路径下)
with open('myfile.txt', 'w') as fp:
fp.write('我\n爱\n你')
#打开读取
with open('myfile.txt') as in_file:
content = in_file.read()
print(content)
#输出:
我
爱
你
或者,要手动关闭文件,您可以放弃使用并直接调用close :
#创建测试文件(当前项目路径下)
with open('myfile.txt', 'w') as fp:
fp.write('我\n爱\n你')
#读取
in_file = open('myfile.txt', 'r')
content = in_file.read()
print(content)
in_file.close()
写入文件
with open('myfile.txt', 'w') as f:
f.write("Line 1")
f.write("Line 2")
f.write("Line 3")
f.write("Line 4")
如果在python云环境的项目根目录打开myfile.txt,你会看到它的内容是 :
Line 1Line 2Line 3Line 4
注意不要使用os.linesep作为行结束符;写入时换行请使用\ n
如果要指定编码,只需将编码参数添加到open函数即可
with open('my_file.txt', 'w', encoding='utf-8') as f:
f.write('utf-8 text')
也可以使用print语句写入文件。在python2和python3中,机制是不同的,但是概念是相同的,你可以把本来会出现在屏幕上的输出结果发送到一个文件中 :
with open('fred.txt', 'w') as outfile:
s = "I'm Not Dead Yet!"
print(s) # 输出到标准控制台
print(s, file = outfile) # 写入到文件
检查文件或路径是否存在
用try/except异常捕获检查:
import errno
path='/tes21323t'
try:
with open(path,'r') as f:
print('文件存在')
except IOError as e:
print('文件或文件夹不存在')
在多线程条件下,如果另一个线程在检查和使用时删除了文件,上面的代码会避免这种情况;但这种情况在下面的代码中有可能会发生:
import pathlib
path = pathlib.Path('/path/to/some/file.txt')
if path.is_file():
#业务逻辑代码
要检查给定的路径是否存在,可以使用上面的Try,或者显式地检查路径 :
import os
path = "/home/myFiles/directory1"
if os.path.exists(path):
#做些什么
用 mmap进行文件灵活读取
使用mmap模块,用户可以将文件映射到内存中,从而随机访问文件中的位置。这是使用普通文件操作的另一种选择。
import mmap
with open('filename.ext', 'r') as fd:
#0: 映射整个文件
mm = mmap.mmap(fd.fileno(), 0)
#在索引5到10处打印字符
print mm[5:10]
# 从mm的当前位置开始打印行
print mm.readline()
#在第5个索引写一个字符
mm[5] = 'a'
#将mm的当前位置设置为文件的开头
mm.seek(0)
#关闭 mmap 对象
mm.close()
替换文件中的文本
import fileinput
#定义要替换的字符串的字典,其实有两个处要替换
replacements = {'Search1': 'Replace1','Search2': 'Replace2'}
for line in fileinput.input('filename.txt', inplace=True):
for search_for in replacements:
replace_with = replacements[search_for]
line = line.replace(search_for, replace_with)
print(line, end='')
检查是否为空文件
import os
#项目文件下的hello.py是否为空
path_to_file='./hello.py'
if os.stat(path_to_file).st_size == 0:
print('这是空的')
else:
print('这不是空的')
#或者:
import os
path_to_file='./hello.py'
if os.path.getsize(path_to_file) > 0:
print('这是空的')
else:
print('这不是空的')
但是,如果文件不存在,两者都会抛出异常。为了避免必须捕捉这样的错误,可以这样做 :
import os
def is_empty_file(fpath):
return os.path.isfile(fpath) and os.path.getsize(fpath) > 0
# 它将返回一个bool值。
多行读取文件
假设您只想在文件的某些特定行之间进行迭代,您可以使用itertools实现这一点 :
import itertools
with open('myfile.txt','w') as file:
file.write('第一行\n第二行\n第三行\n')
with open('myfile.txt', 'r') as f:
for line in itertools.islice(f, 0, 2):
#从第0行开始,读取2行
print(line)
#输出:
第一行
第二行
复制文件夹
import shutil
source='//192.168.1.2/Daily Reports'
destination='D:\Reports\Today'
shutil.copytree(source, destination)
注意:目标目录必须不存在
复制文件:
#准备好两个文件:
with open(input_file, 'r') as in_file, open(output_file, 'w') as out_file:
for line in in_file:
out_file.write(line)
#和上面一样,使用shutil模块:
import shutil
shutil.copyfile(src, dst)
好了,今天的分享就到这里,禁止转载,违者必究