配置文件的读取要点

python支持读取.ini和.conf结尾的配置文件,将配置文件放在外部有利于后续修改。在读取配置文件时通常使用相对路径,这时要先获取当前文件所在文件夹的绝对路径,使用如下代码可以获得:

path = os.path.dirname(__file__)

如果要获取当前文件的相对路径则将dirname改为abspath即可。
以下为读取配置文件完整代码:

import configparser
import os
import shutil

#创建配置文件读取对象
cf = configparser.ConfigParser()
#获取当前文件夹绝对路径
path = os.path.dirname(__file__)
print(path)
#加载配置文件
cf.read(path + "/config.ini")

configparser在对文件进行后续操作之前需要调用read()方法先进行读取,需要注意。
配置文件格式如下:

[filePath]
sourcePath = E:/testCopyFile/sourceDir
destPath = E:/testCopyFile/destDir/

配置文件中需要注意的是字符串类型的配置不需要加引号。

拷贝部分

python中有shutil包来支持文件操作。拷贝文件夹使用方法copytree()来完成,需要注意的是当目标文件夹存在时拷贝会失败报错,此时需要修改源码来避免这个问题(shutil.py源码):

def _copytree(entries, src, dst, symlinks, ignore, copy_function,
              ignore_dangling_symlinks, dirs_exist_ok=False):
    if ignore is not None:
        ignored_names = ignore(os.fspath(src), [x.name for x in entries])
    else:
        ignored_names = set()
    #此处原本没有判断文件夹不存在的判断,这里判断一下当文件夹不存在时创建文件夹避免直接创建可能导致的报错
    if not os.path.exists(dst):
        os.makedirs(dst, exist_ok=dirs_exist_ok)
    errors = []
    use_srcentry = copy_function is copy2 or copy_function is copy

    for srcentry in entries:
        if srcentry.name in ignored_names:
            continue
        srcname = os.path.join(src, srcentry.name)
        dstname = os.path.join(dst, srcentry.name)
        srcobj = srcentry if use_srcentry else srcname
        try:
            is_symlink = srcentry.is_symlink()
            if is_symlink and os.name == 'nt':
                # Special check for directory junctions, which appear as
                # symlinks but we want to recurse.
                lstat = srcentry.stat(follow_symlinks=False)
                if lstat.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
                    is_symlink = False
            if is_symlink:
                linkto = os.readlink(srcname)
                if symlinks:
                    # We can't just leave it to `copy_function` because legacy
                    # code with a custom `copy_function` may rely on copytree
                    # doing the right thing.
                    os.symlink(linkto, dstname)
                    copystat(srcobj, dstname, follow_symlinks=not symlinks)
                else:
                    # ignore dangling symlink if the flag is on
                    if not os.path.exists(linkto) and ignore_dangling_symlinks:
                        continue
                    # otherwise let the copy occur. copy2 will raise an error
                    if srcentry.is_dir():
                        copytree(srcobj, dstname, symlinks, ignore,
                                 copy_function, dirs_exist_ok=dirs_exist_ok)
                    else:
                        copy_function(srcobj, dstname)
            elif srcentry.is_dir():
                copytree(srcobj, dstname, symlinks, ignore, copy_function,
                         dirs_exist_ok=dirs_exist_ok)
            else:
                # Will raise a SpecialFileError for unsupported file types
                copy_function(srcobj, dstname)
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors.extend(err.args[0])
        except OSError as why:
            errors.append((srcname, dstname, str(why)))
    try:
        copystat(src, dst)
    except OSError as why:
        # Copying file access times may fail on Windows
        if getattr(why, 'winerror', None) is None:
            errors.append((src, dst, str(why)))
    if errors:
        raise Error(errors)
    return dst

还有一点是在目标文件夹中不会创建源文件夹,也就是说这个方法相当于是将源文件夹中的所有内容拷贝到目标文件夹中,由于我需要目标文件夹中存在源文件夹所以要在路径中带上源文件夹:

sourcePath = cf.get('filePath', 'sourcePath')
destRootPath = cf.get('filePath', 'destPath')
destCopyPath = destRootPath + '/sourcePath'

if os.path.exists(destCopyPath):
    shutil.rmtree(destCopyPath)
shutil.copytree(sourcePath, destCopyPath)

如果使用循环自己写而不用copytree

import os
import shutil
import configparser

#创建配置文件读取对象
cf = configparser.ConfigParser()
#获取当前文件夹绝对路径
path = os.path.dirname(__file__)
# print(path)
#加载配置文件
cf.read(path + "/config.ini")
#读取路径
sourcePath = cf.get('filePath', 'sourcePath')
destRootPath = cf.get('filePath', 'destPath')
#destCopyPath = destRootPath + '/sourcePath'
if not os.path.isdir(sourcePath):
    print('源路径非文件夹')
    exit(0)
#判断是否有之前的文件,有则清除
firstDirName = os.path.basename(sourcePath)
if os.path.exists(os.path.join(destRootPath, firstDirName)):
    shutil.rmtree(os.path.join(destRootPath, firstDirName))

for root, dirs, files in os.walk(sourcePath):
    #当前源路径最后一级文件夹名称
    currentRootFirstDir = os.path.basename(root)
    if not os.path.exists(os.path.join(destRootPath, currentRootFirstDir)):
        #在目标路径最后一级创建文件夹
        os.mkdir(os.path.join(destRootPath, currentRootFirstDir))
    destRootPath = os.path.join(destRootPath, currentRootFirstDir)
    #创建该层级下所有文件夹
    for childDir in dirs:
        destChildDirPath = os.path.join(destRootPath, childDir)
        os.mkdir(destChildDirPath)
    #创建所有文件
    for childFile in files:
        shutil.copy(os.path.join(root, childFile), destRootPath)

python遍历文件夹下所有对象的方式是根据层级一级一级展示,循环中root为当前所处层级路径,dirs为当前路径下所有文件夹的list,files为所有文件的list。os.path.basename(str)方法为获取参数路径的最后一级名称。


guomz
16 声望1 粉丝

不求做完人,只求做凡人。