Python实战基础20-解密文件及目录操作

任务1 为泸州驰援湖北的89名白衣勇士点赞

【任务描述】

设计python程序,实现用户可以为泸州驰援湖北的89名白衣勇士点赞留言。用户点赞留言内容保存到本地txt文件中。

import os  # 导入os模块
import random  # 导入随机模块
import string  # 导入string模块

# 定义4个变量,存储用户点赞留言信息txt文件的本地路径
path1 = r'C:\output\ekdfs.txt'
path2 = r'C:\output\ekdzyy.txt'
path3 = r'C:\output\fybj.txt'
path4 = r'C:\output\qita.txt'
# 存储西南医科大学附属医院援鄂医护人员名单列表
西南医科大学附属医院 = ['兰四友', '李 多', '邹永胜', '李 强', '吕朝霞', '姜 敏', '邱少平', '兰黎艳', '邢 婷', '王 倩', '钟起燕', '黄桂芳',
              '杨 梅', '周 凯', '高晓岚', '梅松涛', '邹林帆', '冯 磊', '伍 松', '温远淇', '邓 俊', '刘 勇', '赵丽娜', '方蘅雯', '潘永建', '刘西焱', '刘孝元',
              '贺 茜', '曹 鑫', '牟清梦', '陈菊屏', '刘 英', '徐 陶', '尹德锋', '李玉娟', '黄 敏', '曾晓春', '郑 丽', '何雪梅', '张春梅', '周虹羽', '吴宇超',
              '敬 宏', '李 舒', '炜赵越', '刘春丽', '石春霞', '张 佳', '熊 宣', '喻 敏']
# 存储西南医科大学附属中医医院援鄂医护人员名单列表
西南医科大学附属中医医院 = ['雷 波', '刘 操', '林 玲', '许志刚', '罗 英', '高婧臻', '魏光蓉', '魏梦穗', '蓝晓维', '郑雪梅', '周春梅', '李 婧', '梁 敏', '涂连洁', '袁茂思',
                '胡 蓉', '罗 婷', '李晓娟', '曾 理']
# 存储泸州市妇幼保健院医护人员名单列表
泸州市妇幼保健院 = ['何先夜', '王德明', '陈小兰', '李冬梅']
# 存储泸州市其它医院医护人员名单列表
古蔺县人民医院 = ['杨云满', '余 倩']
古蔺县中医医院 = ['刘 铭', '杨 莉']
叙永县人民医院 = ['刘 路', '龚太康']
叙永县中医医院 = ['余 洪', '杨 梅']
泸县中医医院 = ['胡 波', '胡 馨']
泸县第二人民医院 = ['何 春', '李国华']
合江县人民医院 = ['赵 艳', '吴中华']
合江县中医医院 = ['黄 胜', '汤 霞']


def OutputNameList(list):  # 定义函数,功能:输出列表对应的援鄂医院人员名单,参数:list
    j = 0
    for i in range(len(list)):  # 遍历医护人员列表列表
        print(list[i], end=' ')
        j += 1
        if j % 5 == 0:  # 每行输出5个名字
            print("\n")


def OutputQtNameList():  # 定义函数,功能:打印输出泸州市其它区县医院驰援武汉白衣勇士全部名单,参数:无
    print("泸州市其它区县医院驰援武汉医护人员共计16人。具体名单如下:")
    print("古蔺县人民医院 :杨云满 余 倩 共2人")
    print("古蔺县中医医院:刘 铭 杨 莉  共2人")
    print("叙永县人民医院:刘 路 龚太康  共2人")
    print("叙永县中医医院:余 洪 杨 梅  共2人")
    print("泸县中医医院:胡 波 胡 馨   共2人")
    print("泸县第二人民医院:何 春 李国华 共2人")
    print("合江县人民医院:赵 艳 吴中华  共2人")
    print("合江县中医医院:黄 胜 汤 霞  共2人")


def SavaMessage(path, message):  # 定义函数,功能:将用户点赞留言写入到对应文件中,参数:path,message
    file = open(path, "a")  # 以追加模式打开文件
    file.write("用户" + ran_strUserName + "的点赞留言:" + message + "\n")  # 写入一条动态信息
    file.close()  # 关闭文件对象


if __name__ == '__main__':
    print("========= 向泸州援鄂白衣勇士们致敬!!!! ========\n")
    print("   (* ̄︶ ̄)春风十里,最美是战“役”的你(* ̄︶ ̄)    ")
    print("        欢迎您为泸州援鄂医护人员点赞留言    \n")
    print("******没有从天而降的英雄,只有挺身而出的凡人*******\n")
    ran_strUserName = ''.join(random.sample(string.ascii_letters + string.digits, 5))  # 为用户生成随机用户名
    end = 'y'
    operC = 'n'
    while end == 'y' or end == 'Y':
        print("医院序号")
        print("1 西南医科大学附属医院 ")
        print("2 西南医科大学附属中医医院 ")
        print("3 泸州市妇幼保健院 ")
        print("4 泸州市其它区县医院 ")
        print("\n请输入您要点赞的医院序号:", end="")
        operC = input()
        if str(operC) == '1':  # 选择1 西南医科大学附属医院
            print("西南医科大学附属医院驰援湖北医护人员共计" + str(len(西南医科大学附属医院)) + "人。具体名单如下:")
            OutputNameList(西南医科大学附属医院)
            print("\n请输入您要点赞的留言:", end="")
            message = input()  # 保存用户输入的点赞留言
            SavaMessage(path1, message)
            print("您的留言已被记录在:" + "C:\output\ekdfs.txt")  # 打印出用户点赞留言保存的本地路径
            print("\n谢谢您为西南医科大学附属医院援鄂医护人员点赞!\n")
        elif operC == '2': # 选择2 西南医科大学附属中医医院
            print("西南医科大学附属中医医院驰援武汉医护人员共计" + str(len(西南医科大学附属中医医院)) + "人。具体名单如下:")
            OutputNameList(西南医科大学附属中医医院)
            print("\n请输入您要点赞的留言:", end="")
            message = input()  # 保存用户输入的点赞留言
            SavaMessage(path2, message)
            print("您的留言已被记录在:" + "C:\output\ekdzyy.txt")  # 打印出用户点赞留言保存的本地路径
            print("\n谢谢您为西南医科大学附属中医医院医护人员点赞!\n")
        elif operC == '3':  # 选择3 泸州市妇幼保健院
            print("泸州市妇幼保健院驰援武汉医护人员共计" + str(len(泸州市妇幼保健院)) + "人。具体名单如下:")
            OutputNameList(泸州市妇幼保健院)
            print("\n请输入您要点赞的留言:", end="")
            message = input()  # 保存用户输入的点赞留言
            SavaMessage(path3, message)
            print("您的留言已被记录在:" + "C:\output\\fybj.txt")  # 打印出用户点赞留言保存的本地路径
            print("\n谢谢您为泸州市妇幼保健院援鄂医护人员点赞!\n")
        elif operC == '4':  # 选择4 泸州市其它区县医院
            OutputQtNameList()
            print("\n请输入您要点赞的留言:", end="")
            message = input()  # 保存输入的点赞留言
            SavaMessage(path4, message)
            print("您的留言已被记录在:" + "C:\output\qita.txt")  # 打印出用户点赞留言保存的本地路径
            print("\n谢谢您为泸州市其它区县医院援鄂医护人员点赞!\n")
        print("继续相关操作吗(y/n)?", end="")
        end = input()  # 输入结束字符
print("操作结束!")

运行结果:

 Python实战基础20-解密文件及目录操作_第1张图片

用户点赞留言保存在本地txt文件Python实战基础20-解密文件及目录操作_第2张图片

1 基本文件操作

在python中,内置了文件(File)对象。在使用文件对象时,首先需要通过内置的open()方法创建一个文件对象,然后通过该对象提供的方法进行 基本文件操作。

例如,使用文件对象的write()方法向文件中写入内容,以及使用closed方法关闭文件等。

1.1 创建和打开文件

想要操作文件需要现先创建或者打开指定的文件并创建文件对象,可以通过内置的open()函数实现。

语法格式:

file = open(filename[,mode[,buffering]])

参数说明:

file:被创建的文件对象

filename:要创建或打开文件的文件名称,需要使用单引号或双引号括起来。如果要打开的文件和当前文件在同一个目录下,那么直接写文件名即可,否则需要指定完整路径。

mode:可选参数,用于指定文件的打开模式,其参数值如下表,默认是打开模式为只读(即r)。

mode参数的参数值说明
说明 注意
r 以只读模式打开文件,文件的指针将会放在文件的开头 文件必须存在
rb

以二进制格式打开文件,并且采用只读模式。文件的指针将会放在文件的开头,一般用于非文本文件,如图片、声音等

r+ 打开文件后,可以读取文件内容,也可以写入新的内容覆盖原有内容(从文件开头进行覆盖)
rb+ 以二进制格式打开文件,并且采用读写模式。文件的指针将会放在文件的开头。一般用于非文本文件,如图片、声音等
w 以只写模式打开文件 文件存在,则将其覆盖,否则创建新文件
wb 以二进制格式打开文件,并且采用只写模式。一般用于非文本文件,如图片、声音等。
w+ 打开文件后,先清空原有内容,使其变为一个空的文件,对这个空文件有读写权限
wb+ 以二进制格式打开文件,并且采用读写模式。一般用于非文本文件,如图片、声音等
a 以追加模式打开个文件。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入到已有内容之后),否则创建新文件用于写入
ab 以二进制格式打开文件,并且采用追加模式。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入到已有内容之后),否则创建新文件用于写入
a+ 以读写模式打开文件。如果该文件已经存在,文件指针将放在文件的末尾(即新内容会被写入到已有内容之后),否则创建新文件用于读写
ab+ 以二进制格式打开文件,并且采用追加模式。如果该文件已经存在,文件指针将放在文件末尾(即新内容会被写入到已有内容之后),否则创建新文件用于读写

Buffering:可选参数,用于指定读写文件的缓冲模式,指为0表示不缓存;值为1表示缓存;如果大于1,则表示缓冲区的大小。默认为缓存模式。

使用open()方法可以实现以下几种功能:

1.1.1 打开一个不存在的文件时先创建该文件

在默认情况下,使用open()函数打开一个不存在的文件,会抛出如下图的异常:

Python实战基础20-解密文件及目录操作_第3张图片

 要解决上图错误,主要有以下几种方法:

(1)在当前目录下(即与执行的文件相同的目录)创建一个名称为test.txt的文件

(2)在调用open()函数时,指定mode的参数值为w、w+、a、a+。这样,当要打开的文件不存在时,就可以创建新的文件了。

实例1:创建并打开酒城新报最新动态栏目的文件

首先输出一条提示信息,然后调用open()函数创建或打开文件,最后在输出一条提示信息。

print("\n","**********","酒城新报","**********")
file = open('message.txt','w')   # 创建或打开保存酒城新报最新动态信息的文件
print("\n 新闻……\n")

 运行结果:

Python实战基础20-解密文件及目录操作_第4张图片

创建文件夹成功

1.1.2 以二进制形式打开文件

使用open()函数不仅仅可以以文本的形式打开文本文件,而且还可以以二进制形式打开非文本文件,如图片文件、音频文件、视频文件等。

例如,创建一个名为alcohol.png图片的文件,并且应用函数以二进制方式打卡该文件。

# 以二进制方式打开该文件,并输出创建的对象的代码
file = open("alcohol.png",'rb')
print(file)

运行结果:

 Python实战基础20-解密文件及目录操作_第5张图片

从上图可看出,创建的是一个BufferedReader对象。对于该对象生成后,可以再应用其它的第三方模块进行处理。 

1.2 关闭文件

打开文件后,需要及时关闭,以免对文件造成不必要的破坏。关闭文件可以使用close()方法。

语法格式:

file.close()

1.3 打开文件时使用with语句

如果打开文件时抛出了异常,那么将导致文件不能被及时关闭。

为了更好的避免此类问题发生,可以使用Python提供的with语句,从而实现在处理文件时,无论是否抛出异常,都能保证with语句执行完毕后关闭已经打开的文件。

语法格式:

with expression as target:

        with-body

参数说明:

Expression:用于指定一个表达式,这里可以是打开文件的open()函数。

target:用于指定一个变量,并且将expression的结果保存到该变量中。

with-body:用于指定with语句体,其中可以是执行with语句后相关的一些操作语句。如果不想执行任何语句,可以直接使用pass语句代替。

print("\n","**********","酒城新报","**********")
with open('message.txt','w') as file:   # 创建或打开保存酒城新报最新动态信息的文件
    pass
print("\n 新闻……\n")

1.4 写入文件内容 

在实例1中,虽然创建了并打开了一个文件,但是该文件中没有任何内容,它的大小是0KB。python的文件对象提供了write()方法,可以先文件中写入内容。

语法格式:

File.write(string) 

其中,file为打开的文件对象;string为要写入的字符串。 

实例2:向酒城新报的最新动态文件写入一条信息

首先应用open()函数以写方式打开一个文件,然后再调用write()方向该文件中写入一条动态信息,再调用close()方法关闭文件

print("\n","**********","酒城新报","**********")
file = open('message.txt','w') # 创建或打开保存酒城新报最新动态信息的文件
#写入一条动态信息
file.write("泸州援助湖北的89名白衣勇士全部平安归来。 \n")
print('写入了一条新动态。。。。\n')
file.close()  # 关闭文件对象

message.txt文件

Python实战基础20-解密文件及目录操作_第6张图片

注意:在写入文件后,一定要调用close()方法关闭文件,否则写入的内容不会保存到文,件中。 

多学两招:使用writelines()方法,可以向文件中写入一序列的字符串。这一序列字符串可以是由迭代对象产生的,如一个字符串列表。换行需要制定换行符\n。

1.5 读取文件

1.5.1 读取指定字符串

语法格式:

file.read([size]}

参数说明:

file:为打开的文件对象

size:可选参数,用于指定要读取的字符个数,如果省略,则一次性读取所有内容。

例如,要读取message.txt文件中的前8个字符

with open('message.txt','r') as file:  # 打开文件
    string = file.read(8) # 读取前8个字符
    print(string)

运行结果:

Python实战基础20-解密文件及目录操作_第7张图片

使用read(size)方法读取文件时,是从文件的开头读取。如果想要读取部分内容,可以先使用文件对象的seek()方法将文件的指针移动到新的位置,然后再应用read(size)方法读取。

语法格式:

file.seek(offest[,whence])

参数说明:

file:表示已经打开的文件对象

offset:用于指定移动的字符个数,其具体位置与whence参数有关。

whence:用于指定从什么位置开始计算。值为9表示从文件头开始计算,值为1表示从当前位置开始计算,值为2表示从文件尾开始计算,默认为0. 

想要从文件的第4个字符开始读取2个字符

with open('message.txt','r') as file:  # 打开文件
    file.seek(4) # 移动文件指针到新的位置
    string = file.read(2)# 读取2个字符
    print(string)

message.txt里的内容
 

运行结果:

 Python实战基础20-解密文件及目录操作_第8张图片

 说明:再使用seek()方法时,如果采用GBK编码,那么offset的值是按一个汉字(包括中文标点符号)占两个字符计算,而采用utf-8编码,则一个汉字占3个字符,不过无论采用何种编码英文和数字都是按一个字符计算的。这与read(size)方法不同。

实例3,显示酒城新报最新动态栏目内容

print("\n","="*20,"酒城新报最新动态栏目内容","="*20,"\n")
with open('message.txt','r') as file:   # 打开保存酒城新报最新动态栏目内容的文件
    message = file.read()    # 读取全部动态信息
    print(message)           # 输出动态信息
    print("\n","="*28,"over","="*28,"\n")

运行结果:

 Python实战基础20-解密文件及目录操作_第9张图片

1.5.2 读取一行 

使用readline()方法读取一行数据

语法格式:

file.readline()

其中,file为打开的文件对象。同read()方法一样,打开文件时,也需要指定打开模式为r(只读)或者r+(读写)。

实例4,逐行显示酒城新报最新动态栏目的内容

print("\n","="*20,"酒城新报最新动态栏目内容","="*20,"\n")
with open('message.txt','r') as file: # 打开保存酒城新报最新动态栏目内容的文件
 number = 0   # 记录行号
 while True:
     number += 1
     line = file.readline()
     if line =='':
         break    # 跳出循环
     print(number,line,end= "\n")  # 输出一行内容
print("\n","="*28,"over","="*28,"\n")

运行结果:

 Python实战基础20-解密文件及目录操作_第10张图片

1.5.3 读取全部行 

语法格式:

file.readlines()

同read()方法一样,打开文件时,也需要指定打开模式为r(只读)或者r+(读写)

print("\n","="*20,"酒城新报最新动态栏目内容","="*20,"\n")
with open('message.txt','r') as file: # 打开保存酒城新报最新动态栏目内容的文件
 message = file.readlines()#读取全部动态信息
 print(message)  # 输出动态信息
 print("\n","="*28,"over","="*28,"\n")

运行结果:

Python实战基础20-解密文件及目录操作_第11张图片

 从该运行结果可以看出,readlines()方法的返回值为一个字符串列表。在这个字符串列表中,每个元记录一行内容。如果文件比较大时,可以将列表的内容逐行输出。

print("\n","="*20,"酒城新报最新动态栏目内容","="*20,"\n")
with open('message.txt','r') as file: # 打开保存酒城新报最新动态栏目内容的文件
     messageall = file.readlines()
     for message in messageall:
        print(message)
print("\n", "=" * 28, "over", "=" * 28, "\n")

运行结果:

 Python实战基础20-解密文件及目录操作_第12张图片

任务2 实现白酒资料分类整理功能

实现alcohol文件夹中的图片和文档能够分别存放到对应的文件夹中。

import os, shutil  # 导入os模块和shutil模块


def goThroughFiles(path):  # 遍历目录函数  参数: path为原始路径
    print("【", path, "】 目录下包括的文件和目录:")
    for root, dirs, files in os.walk(path, topdown=True):  # 遍历指定目录
        for name in dirs:  # 循环输出遍历到的子目录
            print("●", os.path.join(root, name))
        for name in files:  # 循环输出遍历到的文件
            print("◎", os.path.join(root, name))


def crateFiles(path):  # 创建目录函数  参数: path为要创建目录路径
    if not os.path.exists(path):  # 判断目录是否存在
        os.mkdir(path)  # 创建目录
        print("目录创建成功! ")
        print("新创建的目录路径为:" + path)
    else:
        print("该目录已经存在! ")


def moveFiles(path, new_path, dir_type):  # 移动文件函数 参数: path为原始路径,new_path是移动到的目标目录,dir_type为数据类型
    for root, dirs, files in os.walk(path):  # 取得该文件夹下的所有文件
        for i in range(len(files)):
            if dir_type == 'Pic':  # 数据类型为图片
                if (files[i][-3:] == 'jpg') or (files[i][-3:] == 'png') or (files[i][-3:] == 'JPG'):
                    file_path = root + '/' + files[i]
                    new_file_path = new_path + '/' + files[i]
                    shutil.move(file_path, new_file_path)  # 将每张图片依次移动到新目录下
            elif dir_type == 'Word':  # 数据类型为文档
                if (files[i][-3:] == 'doc') or (files[i][-4:] == 'docx') or (files[i][-3:] == 'wps'):
                    file_path = root + '/' + files[i]
                    new_file_path = new_path + '/' + files[i]
                    shutil.move(file_path, new_file_path)  # 将每个文档依次移动到新目录下


if __name__ == '__main__':  # 主函数
    print("====白酒资料分类整理====")
    path = 'D:\\Alcohol'
    print("遍历目录:")
    goThroughFiles(path)  # 遍历目录
    Pic_path = 'D:\\Alcohol\\Pic'
    Word_path = 'D:\\Alcohol\\Word'
    print("分别创建两个分类子目录 —— Pic和Word:")
    crateFiles(Pic_path)  # 创建新目录
    crateFiles(Word_path)  # 创建新目录
    print("将所有图片移动到子目录Pic文件夹中:")
    moveFiles('D:\\Alcohol', Pic_path, 'Pic')  # 移动图片
    print("successful! 已完成移动!")
    print("将所有文档移动到子目录Word文件夹中:")
    moveFiles('D:\\Alcohol', Word_path, 'Word')  # 移动文档
    print("successful! 已完成移动!")
    print("整理结束后,再次遍历目录:")
    goThroughFiles(path)  # 遍历目录

第5-17行使用os模块的walk()函数用于实现遍历目录的功能。

第11行代码使用os模块的mkdir()函数实现目录的创建。

第23和第28行使用shutil模块的move()函数实现将每张图片/文档依次移动到新目录下。 

2 目录操作

使用内置的os和os.path模块实现直接操作目录。

注意:os模块是python内置的操作系统功能和文件系统相关的模块。该模块中的语句执行通常与操作系统有关,在不同的操作系统上,可能会得到不一样的结果。

常用的目录操作主要有判断目录是否存在、创建目录、删除目录和遍历目录等。

2.1 os和os.path语句

导入OS模块

import os

说明:导入os模块后,也可以使用其子模块os.path,os模块常有的变量有:

  • name:用于获取操作系统类型。例如:os.name输出的结果为nt,则表示是Windows操作系统;如果是posix,则表示是Linux,Unix或Mac OS操作系统。
  • linesep:用于获取当前操作系统上的换行符
  • sep:用于获取当前操作系统所使用的路径分隔符
os模块提供的与目录相关的函数
函数 说明
os.getcwd() 返回当前的工作目录
os.listdir(path) 返回指定路径下的文件和目录信息
os.mkdir(path[, mode]) 创建目录
os.makedirs(path1/path2…[, mode]) 创建多级目录
os.rmdir(path) 删除目录
os.removedirs(path1/path2…) 删除多级目录
os.chdir(path) 把path设置为当前工作目录
os.walk(top[, topdown[, onerror]]) 遍历目录树,该方法返回一个元组,包括所有路径名、所有目录列表和文件列表3个元素
os.path模块提供的与目录相关的函数
方法 说明
os.path.abspath(path) 返回 path 的绝对路径。
os.path.basename(path) 获取 path 路径的基本名称,即 path 末尾到最后一个斜杠的位置之间的字符串。
os.path.commonprefix(list) 返回 list(多个路径)中,所有 path 共有的最长的路径。
os.path.dirname(path) 返回 path 路径中的目录部分。
os.path.exists(path) 判断 path 对应的文件是否存在,如果存在,返回 True;反之,返回 False。和 lexists() 的区别在于,exists()会自动判断失效的文件链接(类似 Windows 系统中文件的快捷方式),而 lexists() 却不会。
os.path.lexists(path) 判断路径是否存在,如果存在,则返回 True;反之,返回 False。
os.path.expanduser(path) 把 path 中包含的 "~" 和 "~user" 转换成用户目录。
os.path.expandvars(path) 根据环境变量的值替换 path 中包含的 "$name" 和 "${name}"。
os.path.getatime(path) 返回 path 所指文件的最近访问时间(浮点型秒数)。
os.path.getmtime(path) 返回文件的最近修改时间(单位为秒)。
os.path.getctime(path) 返回文件的创建时间(单位为秒,自 1970 年 1 月 1 日起(又称 Unix 时间))。
os.path.getsize(path) 返回文件大小,如果文件不存在就返回错误。
os.path.isabs(path) 判断是否为绝对路径。
os.path.isfile(path) 判断路径是否为文件。
os.path.isdir(path) 判断路径是否为目录。
os.path.islink(path) 判断路径是否为链接文件(类似 Windows 系统中的快捷方式)。
os.path.ismount(path) 判断路径是否为挂载点。
os.path.join(path1[, path2[, ...]]) 把目录和文件名合成一个路径。
os.path.normcase(path) 转换 path 的大小写和斜杠。
os.path.normpath(path) 规范 path 字符串形式。
os.path.realpath(path) 返回 path 的真实路径。
os.path.relpath(path[, start]) 从 start 开始计算相对路径。
os.path.samefile(path1, path2) 判断目录或文件是否相同。
os.path.sameopenfile(fp1, fp2) 判断 fp1 和 fp2 是否指向同一文件。
os.path.samestat(stat1, stat2) 判断 stat1 和 stat2 是否指向同一个文件。
os.path.split(path) 把路径分割成 dirname 和 basename,返回一个元组。
os.path.splitdrive(path) 一般用在 windows 下,返回驱动器名和路径组成的元组。
os.path.splitext(path) 分割路径,返回路径名和文件扩展名的元组。
os.path.splitunc(path) 把路径分割为加载点与文件。
os.path.walk(path, visit, arg) 遍历path,进入每个目录都调用 visit 函数,visit 函数必须有 3 个参数(arg, dirname, names),dirname 表示当前目录的目录名,names 代表当前目录下的所有文件名,args 则为 walk 的第三个参数。
os.path.supports_unicode_filenames 设置是否可以将任意 Unicode 字符串用作文件名。

2.2 路径

用于定位一个文件或者目录的字符串被称为一个路径。

2.2.1 相对路径

  • 相对路径:是从当前文件所在的文件夹开始的路径
    • test.txt,是在当前文件夹查找 test.txt 文件
    •  ./test.txt,也是在当前文件夹里找test.txt 文件,./表示的是当前文件夹。
    • ../test.txt,从当前文件夹的上一级文件夹里查找test.txt文件。 ../ 表示的是上一级文件夹
    • demo/test.txt,在当前文件夹里查找 demo 这个文件夹,并在这个文件夹里查找 test.txt文件
import os
print(os. getcwd())   #输出当前目录

with open("demo/message.txt" ) as file:    #通过相对路径打开文件
    pass

多学两招:在指定文件路径时,也可以在表示路径的字符串前面加上字母r(或R),那么该字符串将原样输出,这时路径的分隔符就不需要再转义了。

2.2.2绝对路径

  • 绝对路径:指的是绝对位置,完整地描述了目标的所在地,所有目录层级关系是一目了然的。
    • 例 :如:C:/Users/chris/AppData/Local/Programs/Python/Python37/python.exe,从电脑的盘符开始,表示的就是一个绝对路径。
import os
print(os.path.abspath(r"demo\message.txt"))   #获取绝对路径

2.2.3 拼接路径

可以使用os.path模块提供的join()函数实现。

语法格式:

os.path.join(path1[,path2[,...]])

其中,path1,path2用于代表要拼接的文件路径,这些路径间使用逗号进行分隔。如果在要拼接的路径中,没有一个绝对路径,那么最后拼接出来的是一个相对路径。

import os
print(os.path.join("E:\example" ,"demo\message.txt" ))#拼接字符串

说明:在使用join()函数时,如果要拼接的路径中,存在多个绝对路径,那么以从左到右为序最后一次出现的路径为准,并且该路径之前的参数都将被忽略。

import os
print(os.path.join("E:\example" ,"demo\message.txt" ))#拼接字符串

注意:

  • 使用os.path.join()函数拼接路径时,并不会检测该路径是否真实存在。
  • 把两个路径拼接为一个路径时,不要直接使用字符串拼接,而是使用os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符。 

2.3 判断目录是否存在

语法结构:

os.path.exists(path)

path为要判断的目录,可以采用绝对路径,也可以采用相对路径

返回值:如果给定的路径存在,则返回True,否则返回False

import os
print(os.path.exists("C:\\demo"))  #判断目录是否存在

说明:os.path.exists()函数除了可以判断目录是否存在,还可以判断文件是否存在。 

2.4 创建目录

2.4.1 创建一级目录

语法格式:

os.mkdir(path,mode=0o777)

参数说明:

path:用于指定要创建的目录,可以使用绝对路径,也可以使用相对路径

mode:用于指定数值模式,默认值0777。该参数在非UNIX系统上无效或被忽略。

# 在windows系统上创建一个C:\demo目录
import os
print(os.mkdir("C:\\demo"))  # 创建C:\demo目录

 如果在创建时已经存在将抛出异常FileExisteError异常。Python实战基础20-解密文件及目录操作_第13张图片

 要解决上面的问题,可以在创建目录前,先判断指定的目录是否存在,只有当目录不存在时,才创建。

import os
path = "C:\\demo"    #指定要创建的目录
if not os.path. exists(path):   #判断目录是否存在
    os. mkdir(path)   #创建目录
    print("目录创建成功! ")
else:
print("该目录已经存在! ")

如果指定的目录有多级,而且最后一级的上级目录中有不存在的,则抛出FileNotFoundError异常,并且目录创建不成功。有两种解决方法:1、使用创建多级目录; 2、编写递归函数调用os.mkdir()函数实现。

import os   #导入标准模块os
def mkdir(path):   #定义递归创建目录的函数
    if not os. path. isdir(path):    #判断是否为有效路径
        mkdir(os. path. split(path)[0])   #递归调用
    else:   #如果目录存在,直接返回
        return
    os.mkdir(path)  #创建目录
mkdir("D:/mr/test/demo" )   #调用mkdir递归函数

2.4.2 创建多级目录

makedirs()函数,该函数用于采用递归的方式创建目录。

语法格式:

os.makedirs(name,mode=0o777)

参数说明:

name:用于指定要创建的目录,可以使用绝对路径,也可以使用相对路径

mode:用于指定数值模式,默认值0777.该参数在非UNIX系统上无效或被忽略。

import os
os.makedirs("C:\\demo\\test\\dir\\mr")#创建C:\demo\test\dir\mr目录

2.5 删除目录

语法格式:

os.rmdir(path)

import os
os.rmdir("C:\\demo\\test\\dir\\mr")  #删除C:\demo\test\dir\mr目录

注意:如果要删除的目录不存在,那么将抛出”FileNotFoundError:[WinError2]系统找不到指定文件“异常。因此,在执行os.rmdir()函数前,要先判断该路径是否存在。可使用os.path.exists()

import os
path = "C:\\demo\\test\\dir\\mr"    #指定要创建的目录
if os. path. exists (path):   #判断目录是否存在
    os.rmdir("C:\\demo\\test\\dir\\mr")   #删除目录
    print("目录删除成功! ")
else:
print("该目录不存在! ")

 多学两招:使用rmdir()函数只能删除空的目录,如果想要删除非空目录,则需要使用shutil的rmtree()函数。

import shutil
shutil.rmtree( "C:\\demo\\test" )   #删除C:\demo目录下的test子目录及其内容

2.6 遍历目录

walk()函数的语法格式:
os.walk(top[,topdown],[,onerror][,followlinks])

参数说明:

top:用于指定要遍历内容的根目录

topdown:可选参数,用于指定遍历的顺序,如果值为True,表示自上而下遍历(即先遍历根目录);如果值为False,表示自下而上遍历(即先遍历最后一级子目录),默认值为True。

onerror:可选参数,用于指定错误处理方式,默认为忽略。如果不想忽略也可以指定一个错误处理函数。

followlinks:可选参数,默认情况下,walk()函数不会向下转换成解析到目录的符号链接,将该参数值设置为True,表示用于指定在支持的系统上访问由符号链接指向的目录。

返回值:返回一个包括3个元素(dirpath,dimames,filenames)的元组生成器对象。其中,dirpath表示当前遍历的路径,是一个字符串;dimames表示当前路径下包含的子目录,是一个列表;filenames表示当前路径下包含的文件,也是一个列表。

import os    #导入os模块
tuples = os.walk("E:\\example")#遍历"E:\example"目 录
for tup1e1 in tuples :   #通过for循环输出遍历结果
    print(tup1e1 ,"\n")    #输出每一级目录的元组

 注意:walk()函数只在Unix系统和Windows系统中有效。

实例5,遍历指定目录 

import os   # 导入os模块
path = "E:\\example"       # 指定要遍历的根目录
print("【",path,"】 目录下包括的文件和目录:")
for root, dirs, files in os.walk(path, topdown=True):#遍历指定目录
    for name in dirs:            # 循环输出遍历到的子目录
         print("●",os.path.join(root, name))
    for name in files:           # 循环输出遍历到的文件
         print("◎",os.path.join(root, name))

3 高级文件操作

os模块提供的与文件相关的函数
函数 说明
access(path,accessmode) 获取对文件是否有指定的访问权限(读取/写入/执行权限)。accessmode的值是R_OK(读取)、W_OK(写入)、X_OK(执行)或F_OK(存在如果有指定的权限,则返回1,否则返回0)
chmod(path,mode) 修改path指定文件的访问权限
remove(path) 删除path指定的文件路径
rename(src,dst) 将文件或目录src重命名为dst
stat(path) 返回path指定文件的信息
startfile(path [,operation]) 使用关联的应用程序打开path指定的文件

3.1 删除文件

语法格式:

os.remove(path)

path为要删除的文件路径,可以使用相对路径,也可以使用绝对路径。

例如,删除当前工作目录下的test.txt文件

import os # 导入os模块
os.remove('test.txt') # 删除当前工作目录下的test.txt文件

执行上面的代码后可,如果在当前工作目录下存在test.txt,即可将其删除,否则显示如下图的异常: 

Python实战基础20-解密文件及目录操作_第14张图片

为了避免以上异常,可以在删除文件时,先判断文件是否存在,只有存在时才执行删除操作。

import os   #导入os模块
path = "test.txt"   #要删除的文件
if os.path.exists(path):  #判断文件是否存在
    os.remove(path)     #删除文件
    print("文件删除完毕! ")
else:
    print("文件不存在!")

3.2 重命名文件和目录

语法格式:

os.rename(src,dst)

其中,src用于指定要进行重命名的目录或文件;dst用于指定重命名后的目录或文件。

同删除文件一样,在进行文件或目录重命名时,如果指定的目录或文件不存在,也将抛出FileNotFoundError异常,所以在进行文件或目录重命名时,也建议先判断文件或目录是否存在,只有存在时才进行重命名操作。

例如,想要将“C:\output\dir\test.txt”文件重命名为:“C:\output\dir\message.txt”

import os    #导入os模块
src = r'C:\output\dir\test.txt' #要重命名的文件
dst = r'C:\output\dir\message.txt'  #重命名后的文件
if os.path.exists(src):   #判断文件是否存在
    os.rename(src, dst)    #重命名文件
    print("文件重命名完毕! ")
else:
    print("文件不存在! ")

使用rename()函数重命名目录与命名文件基本相同,只要把原来的文件路径替换为目录即可。

例如,想要将当前目录下的demo目录重名名test

import os     #导入os模块
src = "demo"    #重命名的当前目录下的demo
dst = "test"    #重命名为test
if os.path.exists(src):    #判断目录是否存在
    os. rename(src,dst)    #重命名目录
    print("目录重命名完毕! ")
else:
    print("目录不存在! ")

在使用rename()函数重命名目录时,只能修改最后一级的目录名称,否则将抛出异常

import os     #导入os模块
src = r"C:\output\dir\demo"    #重命名的demo上一级目录dir
dst = r"C:\output\test\demo"    #重命名为test
if os.path.exists(src):    #判断目录是否存在
    os. rename(src,dst)    #重命名目录
    print("目录重命名完毕! ")
else:
    print("目录不存在! ")

运行结果:

Python实战基础20-解密文件及目录操作_第15张图片

3.3 获取文件基本信息

语法结构:

os.stat(path)

其中,path为要获取文件基本信息的文件路径,可以是相对路径,也可以是绝对路径。stat()函数的返回值是一个对象,该对象包含如下表的属性。通过访问这些属性可以获取文件的基本信息。

stat()函数返回的对象的常用属性
属性 说明 属性 说明
st_mode 保护模式 st_dev 设备名
st_ino 索引号 st_uid 用户ID
st_nlink 硬链接号(被连接数目) st_gid 组ID
st_size 文件大小,单位为字节 st_atime 最后一次访问时间
st_mtime 最后一次修改时间 st_ctime 最后一次状态变化的时间(系统不同返回结果也不同,例如,在Windeows操作系统下返回的是文件的创建时间)

实例6,获取文件基本信息

import os   # 导入os模块
fileinfo = os.stat("message.txt") # 获取文件的基本信息
print("文件完整路径:", os.path.abspath("message.txt")) # 获取文件的完整数路径
# 输出文件的基本信息
print("索引号:",fileinfo.st_ino)
print("设备名:",fileinfo.st_dev)
print("文件大小:",fileinfo.st_size," 字节")
print("最后一次访问时间:",fileinfo.st_atime)
print("最后一次修改时间:",fileinfo.st_mtime)
print("最后一次状态变化时间:",fileinfo.st_ctime)

运行结果:

Python实战基础20-解密文件及目录操作_第16张图片

由于上面的结果中的时间和字节数都是一长串的整数,与平时见到的不同,所以一般情况下,为了让显示更加直观,还需要对其进行格式化。

这里主要编写两个函数,一个用于格式化时间,另一个用于格式化代表文件大小的字节数。

import os   # 导入os模块
def formatTime(longtime):
    '''格式化日期时间的函数
       longtime:要格式化的时间
    '''
    import time  # 导入时间模块
    return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(longtime))
def formatByte(number):
    '''格式化日期时间的函数
       number:要格式化的字节数
    '''
    for (scale,label) in [(1024*1024*1024,"GB"),(1024*1024,"MB"),(1024,"KB")]:
         if number>= scale:   # 如果文件大小大于等于1KB
             return "%.2f %s" %(number*1.0/scale,label)
         elif number == 1: # 如果文件大小为1字节
             return "1 字节"
         else:   # 处理小于1KB的情况
             byte = "%.2f" % (number or 0)
    return (byte[:-3] if byte.endswith('.00') else byte)+" 字节"  # 去掉结尾的.00,并且加上单位“字节”
if __name__ == '__main__':
    fileinfo = os.stat("message.txt")  # 获取文件的基本信息
    print("文件完整路径:", os.path.abspath("message.txt"))  # 获取文件的完整数路径
    # 输出文件的基本信息
    print("索引号:", fileinfo.st_ino)
    print("设备名:", fileinfo.st_dev)
    print("文件大小:", formatByte(fileinfo.st_size))
    print("最后一次访问时间:", formatTime(fileinfo.st_atime))
    print("最后一次修改时间:", formatTime(fileinfo.st_mtime))
    print("最后一次状态变化时间:", formatTime(fileinfo.st_ctime))

运行结果:

Python实战基础20-解密文件及目录操作_第17张图片 

你可能感兴趣的:(python基础,python)