python文件操作个人笔记

文件的读取

文件的基础操作

  • 写入文件

    a = [1,2,3,4,5,6,7,8,9]
    with open('./log.txt', 'w') as f:
        for i in a:
            f.write(i)
    
  • 把列表写入文件

    a = [1,2,3,4,5,6,7,8,9]
    with open('./log.txt', 'w') as f:
    	f.writelines(a)
    
  • 整个文件读取

    with open('./log.txt', 'a') as f:
        f.read([size])
        #size,可选,表示要获取多少字符
    
  • 读取一行

    with open('./log.txt', 'a') as f:
        f.readline()
    #读取整个文件可以配合while循环来读取
    
  • 读取一行作为列表返回

    with open('./log.txt', 'a') as f:
        f.readlines()
    
  • 推导式,相当于读取了整个文件,但每一行使通过列表元素来保存的

    # 读取log.txt文件,以保存下读取的数据
    with open('./log.txt', 'r') as f:
        # 使用列表推导式来为每一行数据加上#i与换行符
        r = [j.strip() + f'#{i+1}\n' for i, j in enumerate(f.readlines())]
    
  • 想要判断是否读取完文件可以判断r是否为空即可

    with open('./log.txt', 'a') as f:
        r = f.readline()
    	while True:
            if not r:
                print('文件读取完毕')
    
  • 二进制文件的读取与写入

    • 一般情况下来说,图片与视频等不是由全字符组成的文件都使用二进制的形式来读取以及写入

    • 比如图片的复制

      # 图片,视频等数据的读取与写入
      with open('./head.jpg', 'rb') as f:
          r = f.read()
      
      with open('./head1.jpg', 'wb') as f:
          f.write(r)
      

总结

方法名作用
read()读取全部文档
readline()一行一行读取
readlines()读取全部文档,每一行当成一个元素存入一个列表中
write()写入文档
writelines()把一个列表写入文档,列表元素是怎么样就怎么样写入文档
seek(offset[, whence])offset为正数则往右移动指针,负数反之,whence有三个参数(0:表示从开头位置计算,1:表示从当前位置计算, 2:从末尾位置计算)不填默认是0,但基本是使用0的方法,如果要使用1和2,则需要在模式上加上b模式,否则报错
tell()返回当前指针位置
truncate([size])保留指针前size个字符,其余删除, 不写参数则全部删除
flush()把缓冲区的内容写入文件,但不关闭文件
close()flush()的升级版,写入文件并关闭文件

实例1–在文本每一行末尾加入#1

# 读取log.txt文件,以保存下读取的数据
with open('./log.txt', 'r') as f:
    # 使用列表推导式来为每一行数据加上#i与换行符
    r = [j.strip() + f'#{i+1}\n' for i, j in enumerate(f.readlines())]

with open('./log.txt', 'w') as f:
    # 将处理好的数据写入文件并覆盖之前的文件
    f.writelines(r)

关于with的执行流程,以及内部原理

对象

# 创建一个上下文管理器类
class MyDemo(object):
    # with语句开始时调用的方法
    def __enter__(self):
        print("调用了__enter__方法")
        
    # with语句结束时调用的方法
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("调用了__exit__方法")
        
# 使用with语句
if __name__ == "__main__":
    with MyDome() as f:
        print("-"*50)

结果

调用了__enter__方法
---------------
调用了__exit__方法

方法

# 需要导入contextlib模块
import contextlib
@contextlib.contextmanager
def my_fun(arg):
    print("输出1", arg)
    yield {"a": 123}
    print("输出2")

if __name__ == "__main":
    with my_fun("ccc") as f:
    print(f)
    print('-'*15)

结果

输出1 ccc
{'a': 123}
---------------
输出2

总结

  • 当使用对象来进行上下文管理时,开始时会自动调用类中的__enter__方法,然后回到with关键字中运行相应代码块,结束时会自动调用__exit__方法,如果需要返回一个值到as后面的变量名,则可以在__enter__方法中使用return关键字来返回
  • 使用方法时,会先顺序执行方法内代码,直到遇到yield,返回结果至with关键字中as后面的变量名,然后执行with中的代码块,然后返回方法中执行剩下的代码
  • 注意:使用with关键字时,不必取特意关闭文件流,即使运行过程中报错了

序列化与反序列化

  • python中一切皆对象,对象的本质可以理解为是一个存储数据的数据块,当我们需要从一个区域的数据块移动到里一个区域中时,就需要使用到序列化与反序列化
    • 序列化是指当我们发送数据时需要把对象数据转换成串行化的过程
    • 反序列化与序列化相反,把串行化的数据转换为对象
  • 一般来说发送时的操作时序列化,接收时反序列化
# 进行序列化与反序列化时,需要导入pickle包
import pickle

def dump():
    a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    # 以二进制写入的方式打开文件
    with open('./demo9.txt', 'wb') as f:
        # 将序列化的数据写入文件
        pickle.dump(a, f)
        
    # 以二进制只读的方式打开文件
    with open('./demo9.txt', 'rb') as f:
        # 读取文件中的二进制序列并转换为对象输出
        print(pickle.load(f))

if __name__ == "__main__":
    dump()

注意:打开序列化的文件需要以二进制打开

  • 可以通过把序列化的文件反序列化再重写进文件中达到解码的目的

csv文件的操作

  • csv文件是把表格转换成使用逗号隔开的一个文件

    • 一个表格文件:

      IDNAMEAGE
      01张三18
      02李四19
      03王五18
    • csv文件:

      ID,NAME,AGE

      01,张三,18

      02,李四,19

      03,王五,18

  • csv文件中所有数据都是字符串类型,没有颜色属性合并单元格

# 导入csv模块,csv模块提供了读取和写入csv格式文件的对象
import csv

# 读取csv文件,读取出来的文件数据是一个可迭代对象
with open('./demo10.cvs', 'r', encoding="utf-8") as f:
    r = csv.reader(f)
    for i in r:
        print(i)

# 写入数据到csv文件
with open('./demo10.cvs', 'a', encoding="utf-8") as f:
    # 创建一个csv写入的对象
    r = csv.writer(f)
    # 使用这个对象的writerow方法来写入数据
    r.writerow(["04", "大三", "20"])

也可以一次性写入多个列表

os模块

import os

# 调用cmd终端
os.system("cmd")

# 调用ping来链接网址
os.system("ping www.baidu.com")

# 调用可执行的文件
os.startfile(r"D:\Python\python39\python.exe")
  • os.system相当在命令符窗口或运行窗口执行相关命令
方法名描述
remoe(path)删除指定文件
rename(src,dest)重命名文件或目录
stat(path)返回文件的所有属性
listdir(path)返回目录下的所有子目录与文件,不会返回孙文件与目录
mkdir(path)创建目录
makedirs(path)创建多级目录
rmdir(path)删除目录
removedirs(path)删除多级目录(空目录才能删除)
getcwd()返回当前目录
chdir(path)将path设置为当前目录
walk()遍历目录
sep当前操作系统使用的路径分割符
  • 相对路径都是相对于当前的工作目录来定位的

  • 常见的文件操作

    import os
    
    # 获得操作系统的信息
    print(os.name)
    # window返回的是nt,linux和unix是posix
    
    # 返回路径分割符
    print(os.sep)
    
    # 返回当前操作系统使用的行终止符
    print(repr(os.linesep))
    # repr:返回对象的string格式
    # window为"\r\n" linux为"\n" Mac为"\r"
    
    # 获取文件的信息
    print(os.stat("demo12.py"))
    
    # 当前工作目录
    print(os.getcwd())
    
    # 更改当前目录
    os.chdir("D:")
    
    # 创建文件夹
    os.mkdir("书籍")
    
    # 删除目录
    os.rmdir("书籍")
    
    # 创建多级目录, ../是上一级目录
    os.makedirs("../电影/演员/01")
    
    # 删除多级目录, 只能删除空目录
    os.removedirs("../电影/演员/01")
    
    # 重命名文件与目录
    os.rename("电影", "常见电影")
    
    # 返回目录下的所有子目录与文件
    os.listdir("movie")
    

path模块

  • path是os中的一个子模块,提供目录的相关操作

    方法描述
    getatime(path)文件最后访问时间
    getmtime(path)文件最后修改时间
    isabs(path)判断是否为绝对路径
    isdir(path)判断是否为目录
    isfile(path)判断是否为文件
    exists(path)判断是否有这个路径
    getsize(filename)返回文件大小
    abspath(path)返回文件或文件夹的绝对路径**(只是把当前路径与文件名连接起来罢了)**
    dirname(path)返回当前文件或目录所在目录的名称
    join(path,*paths)连接多个路径
    split(path)对路径进行分割,以列表形式返回
    splitext(path)从路径中分割出文件的拓展名
    walk(path)递归方式遍历目录,返回三个数据,分别是路径、文件夹、文件
  • 对路径的基本操作

    import os
    import os.path
    
    # 判断路径是否是绝对路径
    print(os.path.isabs(r"D:/"))
    
    # 判断是否是目录
    print(os.path.isdir(r"D:/"))
    
    # 判断是否是文件
    print(os.path.isfile(r"D:/"))
    
    # 判断是否有这个路径
    print(os.path.exists(r"D:/"))
    
    # 返回文件大小
    print(os.path.getsize(r"demo13.py"))
    
    # 返回文件的绝对路径
    print(os.path.abspath(r"demo13.py"))
    
    # 返回文件所在目录的名称
    print(os.path.dirname("./demo13.py"))
    
    
  • 判断当前文件是否是文件或目录时,切记切换当前工作路径

import os
import os.path

# 获取当前工作路径
path = os.getcwd()
# 使用walk函数获取当前目录下的所有文件夹及文件
list_files = os.walk(path)
# 返回一个迭代对象,有三个参数,第一个为文件名,第二个为文件夹名,第三个为文件名
for i, j, k in list_files:
    for dir_ in k:
        print(os.path.join(i, dir_))

实例2–获取当前目录的所有.py文件

import os
import os.path

# 遍历这个目录下所有的子目录
def traversal_path(path, n):
    os.chdir(path[n])
    for i in os.listdir(path[n]):
        path.append(os.path.abspath(i))

# 分割文件后缀名,满足是.py为后缀的就输出
def file_suffix(file, n):
    if os.path.splitext(file[n])[-1] == ".py":
        return file[n]

# 具体实现
def main():
    # 存储文件与目录
    file = [r"E:\Users\Administrator\Desktop\pythondemo"]
    file1 = []
    n = 0
    while True:
        if n == len(file):
            break
        elif os.path.isdir(file[n]):
            traversal_path(file, n)
        elif os.path.isfile(file[n]):
            if file_suffix(file, n):
                file1.append(file_suffix(file, n))
        n += 1
    for i in file1:
        r = os.path.split(i)
        print(r[-1], end="\t")

if __name__ == "__main__":
    main()
  • 通过os.path.walk(path)来改进案
def print_file(file):
    # 分割文件后缀,判断是否时py文件
    if os.path.splitext(file)[1] == ".py":
        return file

# 具体实现
def new_main():
    path = r"E:\Users\Administrator\Desktop\pythondemo"
    # os.walk(path)返回一个对象,有三个参数,第一个为文件名,第二个为文件夹名,第三个为文件名
    r = os.walk(path)
    for i, j, k in r:
        for dir_ in k:
            specific = os.path.join(i, dir_)
            # 判断返回是否为None
            if print_file(specific):
                print(os.path.split(print_file(specific))[-1], end="\t")

if __name__ == "__main__":
    new_main()

shutil模块与zipfile模块(拷贝和压缩)

shutil

import shutil

# 拷贝文件
shutil.copyfile("head.jpg", "head2.jpg", ignore=shutil.ignore_patterns("*.txt"))

# 拷贝文件夹
shutil.copytree("../wangyi", "../每日一练/demo")

# 压缩文件
shutil.make_archive("../压缩包/demo1", "zip", "../每日一练")

注意事项

  • 拷贝文件与文件夹时,如果文件与文件夹存在则会报错
  • copyfile方法中,可以选择加上ignore=shutil.ignore_patterns("*.txt")来表示txt文件不进行拷贝
  • shutil的压缩不能压缩文件,只能压缩文件夹,参数(压缩的位置及名字,以什么方式压缩,压缩的内容)

zipfile

import zipfile
import os

# 压缩文件
os.mkdir("../压缩包")
zl = zipfile.ZipFile("../压缩包/demo1.zip", "w")
zl.write("../demo/Test1.txt")
zl.close()

# 解压缩
z2 = zipfile.ZipFile("../压缩包/demo1.zip", "r")
z2.extractall("../压缩包")
z2.close()

注意事项

  • 使用zipfile模块压缩,可以压缩文件及文件夹,当压缩一个文件夹的时候,只会压缩文件夹,当指定存放压缩包的目录不存在时会报错

实例3–返回指定目录所有文件及文件夹

import os
import os.path

# 如果是文件夹就再调用自己,如果是文件就输出
def show_file(r, n):
    # 如果列表长度下标访问完毕则退出循环
    if n == len(r):
        return
    # 如果是路径的话就返回路径下所有文件及文件夹
    if os.path.isdir(r[n]):
        # 通过推导式把每个文件与路径合并起来
        r.extend([os.path.join(r[n], i) for i in os.listdir(r[n])])
    # 调用自身并且n + 1
    show_file(r, n + 1)

# 具体实现
def main():
    path = r"E:\Users\Administrator\Desktop\pythondemo"
    r = [path]
    os.chdir(path)
    show_file(r, 0)
    for i in r:
        print(i)

if __name__ == "__main__":
    main()
  • 更强的递归算法输出所有目录与文件
import os

def get_allfiles(path):
    # 获取路径的文件列表
    child_files = os.listdir(path)
    for file in child_files:
        # 通过for循环来连接生成绝对路径
        filepath = os.path.join(path, file)
        # 判断绝对路径是否是目录
        if os.path.isdir(filepath):
            # 再次调用自己
            get_allfiles(filepath)
        print(filepath)

if __name__ == "__main__":
    get_allfiles(r"E:\Users\Administrator\Desktop\pythondemo")
  • 总结

    • 直接使用os.path.abspath获取目录绝对路径时,只是把当前工作路径和文件名合起来了而已,并不是真正的绝对路径

    • 给函数/方法传递值时,可以直接传值而不必传入一个变量

    • 使用递归时,要加上什么时候不调用自己的条件避免出现死循环

    • 如果需要在局部区域中使用全局变量,需要使用global关键字

      num = 0
      def main():
          # 如果要使用num变量,加上global关键字
          global num
          num += 1
      
posted @ 2021-05-30 10:43  耿集  阅读(67)  评论(0)    收藏  举报