python学习笔记09:文件&目录操作

1. 打开文件的模式

普通

模式 名称 说明
r 以只读方式打开文件。 文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。 如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。 如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb r的二进制模式 -
wb w的二进制模式 -
ab a的二进制模式 -
r+ r的读写模式 不会创建不存在的文件从顶部开始写会覆盖之前此位置的内容,如果先读后写,则会在文件最后追加内容。
w+ w的读写模式 如果文件存在,则覆盖整个文件,如果不存在,则创建。要close 之后才算完成写入
a+ a的读写模式 可读可写,从文件顶部读取内容,从文件底部添加内容,不存在则创建
rb+ r的二进制+读写模式
wb+ w的二进制+读写模式
ab+ a的二进制+读写模式
模式 文件不存在时 是否覆盖
r Y - 报错 -
r+ Y Y 报错 Y
w - Y 创建 Y
w+ Y Y 创建 Y
a - Y 创建 N, 追加写
a+ Y Y 创建 N, 追加写

2. 写文件

例1: 推荐做法: with … as: 不需要手工关闭文件;

>>> with open('tmp.txt', 'w') as fh: #使用with 打开,使用完fh后,不需要手工关闭之;  
...     fh.write('line0\n') # 需要手工加换行符  
...     fh.write('line1\n')  
...  

例2, 常规做法, 打开文件,写入文件,关闭文件;推荐使用with的方法,不需要手工关闭文件

>>> fh = open('tmp.txt', 'w')  
>>> fh.write('line0\n') # 注意不会自动换行,需要手工加换行符;  
>>> fh.write('line1\n')  
>>> fh.close() # 使用完后需要关闭  

3. 读文件

例1: 推荐做法, with … as: 不需要手工关闭文件

>>> with open('tmp.txt', 'r') as fh: #使用with 打开文件,不需要手工关闭文件
...     for line in fh:  
...         print(line, end='') # 行尾不加换行, 或者print(line.strip('\n'))  
...  
输出:  
line0  
line1  

如果待打开的文件中包含中文, 会导致报告UnicodeDecodeError: 'gbk' codec can't decode byte …, 这时, 可以给open加编码参数:

open('tmp.txt', 'r', encoding='UTF-8')

同时获得行号与行文本:

for lineno, line in enumerate(fh, 1)): # 行号以1开头,而不是以0开头
    print(lineno)

例2: 常规做法:打开文件,读取文件,关闭文件;推荐with的做法

>>> fh = open('tmp.txt') #没有声明打开的模式,默认read模式,即第二个参数默认为r
>>> while True:  
...     line = fh.readline()#readline,读取一行内容  
...     if len(line) == 0:#长度等于0表示文件结尾,注意空行的长度为1,换行符占一个长度  
...         break  
...     print(line)  
...  
>>> fh.close()  
   
输出:  
line0  
<空行> #因为print会默认在结尾加换行符  
line1  
<空行>  

几个read函数

>>> fh.read()       #读取整个文件,将之放到一个字符串变量中;  
>>> fh.readline()   #每次只读取一行,放到字符串中;  
>>> fh.readlines()  #读取整个文件,将之分析成一个列表;  

例3:

>>> with open('tmp.txt', 'r') as fh:  
...     txt = fh.read() # 'line0\nline1\n',读取所有行,返回str;  

例4:

>>> with open('tmp.txt', 'r') as fh:  
...     txt0 = fh.readline()# 'line0\n',每次读取一行;  
...     txt1 = fh.readline().strip() # 'line1',每次读取一行, str.strip()可以去行尾换行符和空格;  

例5:

>>> with open('tmp.txt', 'r') as fh:  
...      list_txt = fh.readlines() # ['line0\n', 'line1\n'],读取所有行,放到list中;  

4. 读取/写入压缩文件(.gz)

使用gzip模块读取gz文件:

读取

import gzip  
with gzip.open('file.txt.gz', 'rb') as fid: # 读取模式为rb  
for line in fid:  
    line = line.decode() # 读入的line是二进制格式(b''), 需要解码  
    line = line.strip('\n') # 去掉换行符  
    print(line)  

写入:

import gzip  
fh = gzip.open('file.txt.gz', 'wb')
fh.write('1234'.encode())
fh.close()

5. with…as语句

可以使用with语句代替try…finally语句,好处是语法比较简洁。另见第15.2节。
不管在处理文件过程中是否发生异常,都能保证with语句执行完毕后关闭打开的文件句柄。

>>> with open(file, 'r') as f:
...     print(f.read())

等价于如下写法:

>>> try:
...     f = open(file, 'r')
...     print(f.read())
... finally:
...     if f:
...         f.close()
...

6. 文件测试/文件判断

1.判断文件/目录是否存在

>>> os.path.exists(test_file) # True | False
>>> os.path.exists(test_dir)# True | False

2.判断文件是目录或是普通文件

>>> os.path.isfile(test_target) # test_target是普通文件时,返回True, "是目录"或"目录不存在"时,返回False;
>>> os.path.isdir(test_target) # test_target是目录时,返回True, "是普通文件"或"文件不存在"时,返回False;

3.判断文件是否可读写

>>> os.access(test_file, os.F_OK) # 文件存在,返回True;
>>> os.access(test_file, os.R_OK) # 文件可读,返回True;
>>> os.access(test_file, os.W_OK) # 文件可写,返回True;
>>> os.access(test_file, os.X_OK) # 文件可执行,返回True;

7. 文件、目录、路径

获取程序所在目录:

#假设py文件 /test/path/a.py的内容为  
import os, sys  
print(f'os.getcwd() = {os.getcwd()}')  
print(f'sys.path[0] = {sys.path[0]}')  
  
#用户在/home/g444054/目录下执行  
$ python /test/path/a.py  
os.getcwd() = /home/g444054 # 返回的是执行命令的路径   
sys.path[0] = /test/path    # 返回的是脚本所在的路径   

列出指定目录下的文件(指定目录为空时,默认为当前目录),返回列表,注意:返回的list元素不包含对应的path,只是文件名。要递归目录, 需要使用os.walk

>>> os.listdir(path)  
['file0', 'file1', 'dir0']  

创建目录, 删除目录, 删除文件, 复制文件

>>> os.mkdir(path)# 创建目录;  
>>> os.rmdir(path)# 删除目录, 要递归删除使用shutil.rmtree;  
>>> os.remove(file) # 删除文件;  
>>> os.rename('test.txt', 'test.py') # 重命名  
>>> shutil.copy('/home/g004440**/.cshrc', '/home/n004435**/') #复制文件  
>>> shutil.copytree('/home/g004440**/dir0', '/home/g004440**/dir.bak') #复制目录和内部所有文件. 目标文件夹不能已经存在.  
>>> shutil.rmtree(path) # 删除目录树, 必须指向文件夹, 不能是符号链接.  

切换目录

>>> os.chdir(path)# 切换目录  

文件大小(字节)

>>> os.path.getsize(filename) #返回文件大小,对目录无效  
65525  

拆分指定路径: os.path.split(path)(必须有一个参数),返回一个包含两个元素的元组:
[0]: 文件或目录所在的路径,也可以通过os.path.dirname(path)获取
[1]: 目录名或文件名

>>> os.path.split('/home/g004440**/script')  
('/home/g004440**', 'script')  
>>> os.path.split('/home/g004440**/script/') # 末尾包含'/',全部归到路径  
('/home/g004440**/script', '') # 不管script是不是一个目录  
>>>  
>>> os.path.split('/home')  
('/', 'home')  
>>> os.path.split('/home/')  
('/home', '')  

拆分文件扩展名,返回一个元组

>>> os.path.splitext('/home/g004440**/.vim.rc')  
('/home/g004440**/.vim', '.rc')  

合并路径,如果Linux会用/合并,Win中是\

>>> os.path.join('/home', 'g00444054', 'script') # 合并路径,  
'/home/g004440**/script'  
>>> os.path.join('/home', 'g00444054', 'script', '')  
'/home/g004440**/script/' # 末尾有空元素会多返回一个'/'  
>>> os.path.join('', '/home', '', 'g00444054', 'script')  
'/home/g004440**/script' # 前面或中间有空元素,不影响结果.  

获取路径的绝对路径os.path.abspath(path)或os.path.realpath(path)

>>> os.path.abspath('.')  
'/home/g004440**/script'  
>>> os.path.abspath('..')  
'/home/g004440**'  
>>> os.path.abspath('../xxx') # xxx可以不存在。  
'/home/g004440**/xxx'  
>>> os.path.realpath('../xxx') # xxx可以不存在。  
'/home/g004440**/xxx'  

8. 遍历目录操作

目录结构test_walk

test_walk/  
    |-- dir0  
    |-- dir1  
    |    |-- dir1.file0  
    |    |-- dir1.file1  
    |-- dir2  
    |    |-- dir2.dir0  
    |    |-- dir2.dir1  
    |-- file0  
    `-- file1  

代码

for _s_one_path, _list_dirs, _list_files in os.walk('test_walk'):  
    print(f'{_s_one_path}/')         #test_walk目录中的所有层级目录
  
    for _s_one_dir in _list_dirs:    #当前_s_one_path目录中一个层级中的dir
        print(f'    {_s_one_dir}/')  
  
    for _s_one_file in _list_files:  #当前_s_one_path目录中一个层级中的file
        print(f'    {_s_one_file}')  
  
    print('')  

输出:

test_walk/  
    dir0/   # test_walk目录中的3个dir  
    dir1/  
    dir2/  
    file0   # test_walk目录中的2个file  
    file1  
  
test_walk/dir0/ # test_walk/dir0目录中没有dir和file  
     
test_walk/dir1  # test_walk/dir0目录中没有dir, 有2个file  
    dir1.file0  
    dir1.file1  
     
test_walk/dir2  # test_walk/dir2目录中有2个dir, 没有file  
    dir2.dir0/  
    dir2.dir1/  
     
test_walk/dir2/dir2.dir0  # test_walk/dir2/dir2.dir0目录中没有dir和file  
     
test_walk/dir2/dir2.dir1  # test_walk/dir2/dir2.dir1目录中没有dir和file  
posted @ 2020-07-03 10:54  编程驴子  阅读(180)  评论(0编辑  收藏  举报