[Python]-10-文件读写(中)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Python]-10-文件读写(中)相关的知识,希望对你有一定的参考价值。

引言

这篇文章介绍如何使用python的os与shutil模块,对文件或文件夹进行读写、创建、删除等操作。

文章目录

0×2.文件夹相关操作
a.拼接路径
b.获取子目录名
c.规范化路径输出
d.判断目录或文件是否存在
e.列出目录下所有文件
f.创建删除文件夹
g.通配符的使用
h.文件和文件夹重命名
i.文件夹复制

0×2.文件夹相关操作

a.拼接路径

os.path.join()函数用于拼接路径,它不会判断两个路径是否存在,仅仅完成将前面的路径和后面的路径进行拼接的功能,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
path1="/www"
path2="qingsword/com"
print(os.path.join(path1,path2))

#输出
/www/qingsword/com

b.获取子目录名

有时候我们可能需要获取某个路径下最后一个子目录的名称,python提供了一个os.path.split()方法用于切割路径,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
path1="/www/qingsword/com"
#split()方法返回一个元组,包含两个元素,父路径和子目录名
print(os.path.split(path1))
#可以直接使用两个对象来接收元组中这两个元素
p1,p2=os.path.split(path1)
print(p1)
print(p2)

#输出
(\'/www/qingsword\', \'com\')
/www/qingsword
com

如果想递归获取路径中每一层目录的名称,可以使用下面的方法:

#!/usr/bin/env python
#coding=utf-8
import os
#------
def split_fully(path):
    """递归获取路径中每一层目录的名称,返回一个元组"""
    parent_path,dir_name=os.path.split(path)
    if dir_name=="":
        return (parent_path,)
    else:
        return split_fully(parent_path)+(dir_name,)

path1="/www/qingsword/com"
for p in split_fully(path1):
    print(p)

#输出
/
www
qingsword
com

在上面这个实例中,程序的运行流程是这样的,split_fully()函数首先将"/www/qingsword/com"路径分割成"/www/qingsword"与"com",因为dir_name不为空,所以执行return split_fully(parent_path)+(dir_name,),这一句中(dir_name,)就相当于(com,)而前半段使用父路径再次调用函数本身,外层函数将被挂起等待split_fully(parent_path)结果的返回,这一次的调用parent_path="/www/qingsword";

第一次调用自身"/www/qingsword"被分割成"/www"和"qingsword",由于dir_name不为空,函数第二次调用自身,此时如果我们将所有变量都代入数据,返回最外层被挂起的函数查看return,应该是这样的结构return split_fully("/www")+(qingsword,)+(com,);

第二次调用自身,"/www"被分割成parent_path="/",dir_name="www"不为空,程序会第三次调用自身,这一次parent_path,dir_name=os.path.split(path)分割后,dir_name为空,所以返回parent_path="/",最后一层一层返回,最外层的结构就变成了return ("/",)+("www",)+("qingsword",)+("com",),只需要遍历这个元组,就能得到每个元素的值。

c.规范化路径输出

在路径中,"."表示当前目录,".."表示父目录,如果我们不希望这些符号出现,可以使用os.path.normpath()函数,它不仅可以规范路径,将两个点自动解析成父目录,还能去除路径中多余的斜杠,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
path1="///www/./qingsword////hidden/..//com"
print(os.path.normpath(path1))

#normpath会自动清除目录中多余的斜杠,并且将..解析为父目录,所以hidden目录后面的..就相当于在hidden目录里面执行了一个"cd .."命令,返回了qingsword目录中,而www目录后面的.就代表当前目录,所以直接去掉了,最后输出如下
/www/qingsword/com

d.判断目录或文件是否存在

os.path.exists()函数能够判断目标是否存在,但不能判断目标是文件还是目录,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
path1="/www/qingsword/com"
print(os.path.exists(path1))
print(os.path.exists("textfile"))

#输出,如果目标存在就返回True,不存在就返回False
TRUE
FALSE

e.列出目录下所有文件

使用os.listdir()函数,可以返回目标目录下所有文件夹和文件的名称列表,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
#获取当前脚本所在目录的绝对路径
file_path=os.path.abspath(".")

#遍历列表,打印出每个文件或文件夹的名称
for name in os.listdir(file_path):
    print(name)

#如果想打印出目录下每个文件或文件夹的完整路径,可以修改print函数,下面两种方法效果相同
print(file_path+"/"+name)
print(os.path.join(file_path,name))

如果想要对listdir的输出进行排序,可以使用sorted()函数,默认按照字母顺序排列,并且区分大小写,大写字母>符号>小写字母,这样for中的name会按照排序后的顺序读取并拼接:

#!/usr/bin/env python
#coding=utf-8
import os
file_path=os.path.abspath(".")
#排序输出
for name in sorted(os.listdir(file_path)):
    print(os.path.join(file_path,name))

上面的实例仅仅能够遍历某个目录下的文件和目录,但不能进行递归查询,也就是说,这个目录下的子目录中的文件是无法被搜索到的,下面提供一种遍历子目录文件的方法:

#!/usr/bin/env python
#coding=utf-8
import os
#------
def print_tree(path):
    """递归目录"""
    if os.path.isdir(path):
        #遍历目录,打印绝对路径
        for name in os.listdir(path):
            abs_path=os.path.join(path,name)
            print(abs_path)
            #如果路径为目录,调用自身,打印子目录内容
            if os.path.isdir(abs_path):
                print_tree(abs_path)

print_tree("/home/qing/test")

再来看一个实例,读取目录下的文件,显示每个文件的绝对路径,大小和最后修改时间:

#!/usr/bin/env python
#coding=utf-8
import os
import time
#------
def list_dir(path):
    """打印目录中文件或文件夹的大小,最后修改时间和绝对路径"""
    if os.path.isdir(path):
        for name in os.listdir(path):
            abs_path=os.path.join(path,name)
            sz=os.path.getsize(abs_path)
            modify_time=time.ctime(os.path.getmtime(abs_path))
            print("Size:%-8d Last Modify Time:%-25s Path:%s"%(sz,modify_time,abs_path))

list_dir("/home/qing/test")

利用列表生成式可以很简洁的打印出某一类型的文件列表,例如:

#!/usr/bin/env python3
#coding=utf-8
import os
#列出脚本所在文件夹中所有文件和文件夹名称
print([x for x in os.listdir(os.path.abspath("."))])

#列出脚本所在文件夹中所有子文件夹名称
print([x for x in os.listdir(os.path.abspath("."))\\
       if os.path.isdir(x)])

#列出脚本所在文件夹中所有py文件名称
print([x for x in os.listdir(os.path.abspath("."))\\
       if os.path.isfile(x) and os.path.splitext(x)[1]==".py"])

f.创建删除文件夹

创建文件夹:

#!/usr/bin/env python
#coding=utf-8
import os
#os.mkdir()函数一次只能创建一个文件夹
if not os.path.exists("qingsword"):
    os.mkdir("qingsword")
#os.makedirs()函数能够一次性递归创建多个文件夹
if os.path.isdir("qingsword"):
    os.makedirs("qingsword/1/2/3/4")

Ps:在创建文件夹的过程中,如果目标存在,则会抛出一个"FileExistsError"异常。

删除文件夹:

#!/usr/bin/env python
#coding=utf-8
import os
import shutil

if os.path.isdir("qingsword"):
    os.rmdir("qingsword/1/2/3/4")
    shutil.rmtree("qingsword")

Ps:os.rmdir()函数只能删除单个文件夹且文件夹下必须为空,否则会抛出一个"OSError"异常,而shutil模块的rmtree方法能够一次性删除目录及下面的所有文件。

g.通配符的使用

在python路径操作中,有下面这些比较常用的通配符:

  • 匹配多个字符;

? 匹配单个字符;

[...] 匹配括号中的单个字符,可以指定多个字符或字符范围,例如:[ABCD]代表ABCD任意一个都能匹配;[a-z]匹配小写字母表中任意一个字符;[0-9]匹配0-9数字中的任意一个;

[!...]不匹配括号中指定的任意一个或某个范围中的一个;

在python中有一个通配符模块glob,这个模块的glob()函数同os.listdir()类似,都能返回某个目录下的文件,但glob.glob()函数更加强大,它能够配合通配符返回指定的文件类型,请看下面的实例:

#!/usr/bin/env python
#coding=utf-8
import os
import glob
path1="/home/qing/test"
if os.path.isdir(path1):
    #返回path1目录下所有py后缀的文件
    print(glob.glob(os.path.join(path1,"*.py")))
    #返回文件名最后一个字符在a-d范围内的py文件
    print(glob.glob(os.path.join(path1,"*[a-d].py")))
    #返回文件名为四个字符的py文件
    print(glob.glob(os.path.join(path1,"????.py")))
    返回文件名为三个字符且最后一个字符不在b-f范围内的py文件
    print(glob.glob(os.path.join(path1,"??[!b-f].py")))
    #这是glob函数强大的地方,递归path1目录,返回目录以及子目录中所有py文件
    print(glob.glob(os.path.join(path1,"*/*.py")))

Ps:glob.glob()函数返回类型为列表。

h.文件和文件夹重命名

os模块的rename方法可以实现文件和文件夹重命名的操作,请看下面的实例:

#!/usr/bin/env python3
#coding=utf-8
import os
#如果file1存在且file2不存在,将file1改名为file2,file1可以是文件或文件夹的绝对或相对路径
if os.path.exists("file1") and not os.path.exists("file2"):
    os.rename("file1","file2")

i.文件夹复制

可以使用shutil模块的copytree方法来拷贝一个目录到目标位置,例如:

#!/usr/bin/env python3
#coding=utf-8
import os
import shutil
def copyDir(src,dst):
    """完成源文件夹到目标位置的复制"""
    if os.path.isdir(src) and not os.path.exists(dst):
        shutil.copytree(src,dst)
        print("复制成功。")
    else:
        print("复制失败。")
def moveDir(src,dst):
    """完成源文件夹到目标位置的移动"""
    if os.path.isdir(src) and not os.path.exists(dst):
        shutil.copytree(src,dst)
        shutil.rmtree(src)
        print("移动成功。")
    else:
        print("移动失败。")   

moveDir("dir1","dir2")
copyDir("dir1","dir2")

以上是关于[Python]-10-文件读写(中)的主要内容,如果未能解决你的问题,请参考以下文章

[Python]-10-文件读写(上)

python open with读写编辑文件

Python代码中打开txt文件(非读写)

[Python]-10-文件读写(下)

我在哪里更改此 Python 代码片段以将临时文件保存在 tmp 文件夹中?

linux下c通过虚拟地址映射读写文件的代码