python基础五:python实用的几个文件操作的案例

1. 写在前面

今天整理几个python关于文件操作的几个案例, 主要包括用python进行文件的读写, 获取文件名, 获取文件的后缀名和批量修改文件的后缀。这次整理的几个方法依然都是从使用的角度出发。比如我需要统计某个txt文件中每个单词的出现次数, 再比如我需要批量的修改文件的后缀等。 以后涉及到python的文件读写操作的内容, 会继续在这篇文章中进行添加。

Ok, let’s go!

2. python进行文件的读写

文件的读写在python中比较常见, 文件读取的时候, 首先要判断文件是否存在, 若文件操作就进行读取, 否则报错。

2.1 文件读操作

文件读操作可以的函数有read(), 这个是读取整个文件, 还有readlines()这个是一行行的进行读取并保存到列表中。 下面直接上代码:

import os

def read_file(filename):
    if os.path.exists(filename) is False:
        raise FileNotFoundError('%s not exists' % (filename,))
    
    f = open(filename, encoding='utf-8')   # 后面那个是指定编码  一般平台默认编码格式是utf-8
    content = f.read()
    f.close()
    return content

# 另一种写法
def read_file(filename):
    if os.path.exists(filename) is False:
        raise FileNotFoundError('%s not exists' % (filename,))
    
    with open(filename, encoding='utf-8') as f:
        content = f.read()    #  这时候读完了之后自动关闭
        
    return content

content = read_file('a.txt')
content


## 
'Hey, Python\n\nI just love      Python so much,\nand want to get the whole  Python stack by this 60-days column\nand believe Python !'

下面是按行读的效果:

"""文件按行读"""
def read_file_line(filename):
    if not os.path.exists(filename):
        raise FileNotFoundError('%s not exists' % filename)
    
    with open(filename, encoding='utf-8') as f:
        content = f.readlines()
    
    return content

con = read_file_line('a.txt')

con

## 
['Hey, Python\n',
 '\n',
 'I just love      Python so much,\n',
 'and want to get the whole  Python stack by this 60-days column\n',
 'and believe Python !']

好了, 基于上面的这个就可以写一个统计文件里面所有单词的出现次数了。 先走一遍这个过程: 我获取到文件的内容, 然后进行分词, 分开之后才能统计个数。

# 下面是一个统计单词个数的例子
from collections import defaultdict  
#这里的defaultdict(function_factory)构建的是一个类似dictionary的对象,
#其中keys的值,自行确定赋值,但是values的类型,是function_factory的类实例,
#而且具有默认值。比如default(int)则创建一个类似dictionary对象,里面任何的values都是int的实例,
#而且就算是一个不存在的key, d[key] 也有一个默认值,这个默认值是int()的默认值0.
import re

rec = re.compile('\s+')      # 匹配一个或者多个空格
dd = defaultdict(int)

with open('a.txt', 'r+') as f:
    for line in f:
        clean_line = line.strip()
        if clean_line:
            words = rec.split(clean_line)
            for word in words:
                dd[word] += 1

dd = sorted(dd.items(), key=lambda x: x[1], reverse=True)
dd

##   结果如下:
[('Python', 4),
 ('and', 2),
 ('Hey,', 1),
 ('I', 1),
 ('just', 1),
 ('love', 1),
 ('so', 1),
 ('much,', 1),
 ('want', 1),
 ('to', 1),
 ('get', 1),
 ('the', 1),
 ('whole', 1),
 ('stack', 1),
 ('by', 1),
 ('this', 1),
 ('60-days', 1),
 ('column', 1),
 ('believe', 1),
 ('!', 1)]

上面这个案例有时候还是比较实用的。

2.2 文件写操作

文件写操作时,需要首先判断要写入的文件路径是否存在。若不存在,通过 mkdir 创建出路径;否则,直接写入文件:

def write_to_file(file_path, file_name):
    if not os.path.exists(file_path):
        os.mkdir(file_path)
    
    
    whole_path_filename = os.path.join(file_path, file_name)
    
    to_write_content = ''' 
                        Hey, Python
                        I just love Python so much,
                        and want to get the whole python stack by this 60-days column
                        and believe!
                        '''
    
    with open(whole_path_filename, mode='w', encoding='utf-8') as f:
        f.write(to_write_content)

3. 获取文件名及文件的后缀名

有时候我们拿到一个文件名的时候, 名字上带有路径, 这时候我们可以用os.path.split方法实现路径和文件名的分离。

file_ext = os.path.split('./data/py/test.py')
ipath, ifile = file_ext

print(ipath, ifile)

##
./data/py       test.py

os.path 模块,splitext 能够优雅地提取文件后缀。

file_extension = os.path.splitext('./data/py/test.py')
file_extension     # .py

基于上面的这个操作, 就可以获取某个目录下面指定后缀名的文件

# 获取某个目录下指定后缀名的文件
def find_file(work_dir, extension='jpg'):
    lst = []
    for filename in os.listdir(work_dir):
        #print(filename)
        splits = os.path.splitext(filename)
        ext = splits[1]      # 拿到扩展名
        if ext == '.'+extension:
            lst.append(filename)
    return lst

r = find_file('E:\Jupyter Notebook\Python', 'ipynb')
print(r)

## 结果
['Day1-Day2.ipynb', 'Day10_python文件操作案例.ipynb', 'Day3-Day4.ipynb', 'Day5-Day6.ipynb', 'Day7-Day8.ipynb', 'Day9_字符串操作与正则.ipynb']

这个还是很实用的, 比如在CNN的一些任务中, 很多图片都是以.jpg的形式存放到文件夹里面的, 我们这时候就需要先获取到所有的.jpg文件, 然后再通过一些方式把图片转成矩阵的表示形式, 这样我们的网络才会认识。

下面再整理一个批量修改文件后缀名的例子, 比如我想把某个目录下所有的.xls转成.xlsx文件。这个要怎么做? 依然是先梳理一下逻辑:

  1. 首先要遍历所给的目录
  2. 拿到各个文件的后缀名
  3. 看看后缀名是否是需要修改的后缀名, 如果是就进行重命名操作

有了这个逻辑, 代码就比较好写了。

def batch_rename(work_dir, old_ext, new_ext):
    for filename in os.listdir(work_dir):
        
        # 获取文件后缀
        split_file = os.path.splitext(filename)
        file_ext = split_file[1]
        if old_ext == file_ext:   # 定位需要修改后缀名的文件
            newfile = split_file[0] + new_ext   # 修改后文件的完整名称
            
            # 重命名
            os.rename(
                os.path.join(work_dir, filename),
                os.path.join(work_dir, newfile)
            )

下面基于这个整理一点新的知识, 就是如果我是想把上面这个写到.py的文件里面, 我从命令行里运行这个.py文件的时候想把上面的三个参数传进去, 那么我应该怎么传呢?

这时候,就需要用到python的一个模块叫做argparse, 这是python用于解析命令行参数和选项的标准模块, 具体的我目前也不是了解太多, 但是我见过的一般用这个东西的时候, 基本分为三步:

  • 创建 ArgumentParser() 对象
  • 调用 add_argument() 方法添加参数
  • 使用 parse_args() 解析添加的参数

换成代码的方式就是:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("x", type=int)
parser.add_argument('y', type=int)
args = parser.parse_args()

# 这样就能通过命令行传递过参数x y来, 我们可以通过下面代码获取到这两个参数
x=args.x
y=args.y
print(x,y)

如果想详细了解每个函数里面具体参数到底是干啥用的, 去官网https://docs.python.org/2/howto/argparse.html
所以这里主要是记录一下这个东西到底咋用, 而放到这里例子里面我们就可以这样写(test.py):

def batch_rename(work_dir, old_ext, new_ext):
    print(new_ext)

    for filename in os.listdir(work_dir):
        
        # 获取文件后缀
        split_file = os.path.splitext(filename)
        file_ext = split_file[1]
        if old_ext == file_ext:   # 定位需要修改后缀名的文件
            newfile = split_file[0] + new_ext   # 修改后文件的完整名称
            
            # 重命名
            os.rename(

                os.path.join(work_dir, filename),
                os.path.join(work_dir, newfile)
            
            )
    print("完成重命名")
    print(os.listdir(work_dir))


def main():
    # 命令行参数
    parser = argparse.ArgumentParser(description='工作目录文件后缀名修改')
    parser.add_argument('work_dir', metavar='WORK_DIR', type=str, nargs=1, help='修改后缀名文件目录')
    parser.add_argument('old_ext', metavar='OLD_EXT', type=str, nargs=1, help='原来的后缀')
    parser.add_argument('new_ext', metavar='NEW_EXT', type=str, nargs=1, help='新的后缀')
    
    args = vars(parser.parse_args())
    
    # 从命令行参数中依次解析出参数
    work_dir = args['work_dir'][0]
    old_ext = args['old_ext'][0]
    
    if old_ext[0] != '.':
        old_ext = '.' + old_ext
    
    new_ext = args['new_ext'][0]
    if new_ext[0] != '.':
        new_ext = '.' + new_ext
    
    batch_rename(work_dir, old_ext, new_ext)

if __name__ == '__main__':
    main()

那么我们应该怎么用呢? 打开命令行, 输入:

python test.py E:\test xls xlsx     # 后面三个参数分别就是目录, 旧后缀名, 新后缀名

这代码就不解释了。

为什么非要介绍一下argparse这个库呢? 当然, 如果是用jupyter notebook这样的工具写点小的python demon 或者用keras啥的搭建些神经网络什么的, 一般是用不着这个东西的。 但是如果是放在项目的角度, 我们一般是习惯把整个任务拆成很多小块, 然后每个块写一个.py文件, 这样组织成一个大的工程。 比如训练一个复杂的神经网络做一个时序预测, 这时候如果用jupyter的话, 写出来的代码会非常的长, 并且不易读和维护, 这时候就可以考虑分成四块, 数据集的构造, 模型的建立, 模型的训练和模型的预测。 每一块写到一个.py文件里面。 这样代码的维护和读起来就比较简单了, 所以比较大的项目一般是分成很多个.py的。

那讲了这么一大堆, 和argparse有啥关系呢? 这个就比较适合于我通过命令行运行train.py这样的代码训练神经网络的时候传一些必要的参数过去, 比如batch_size, epoch, lr, 输入输出的维度等等吧。 你可能又会说为啥不直接声明一些变量先存好这些参数呢, 这样的话即使用命令行直接python train.py不就完事? 当然这个方法可以, 但是如果想频繁的改变参数,且是在Linux的黑窗口下, 光反复的打开关闭.py文件其实是挺麻烦的, 不如留一个传参的接口, 所以这时候可能会用到这个库。 就比如下面的这个代码的开头(train.py):

在这里插入图片描述
这时候,我们就可以直接在命令行python train.py 然后后面带着相应的参数即可。

猜你喜欢

转载自blog.csdn.net/wuzhongqiang/article/details/106820323