def process_nested_folders(root_folder, output_dir, workers=20): “”" 新增逻辑:遍历三级目录结构 “”" os.makedirs(output_dir, exist_ok=True) 遍历所有三级文件夹 for root, dirs, files in os.walk(root_folder): rel_path = os.path.relpath(root, root_folder) depth = len(rel_path.split(os.sep)) if rel_path != “.” else 0 if depth == 2: # 三级文件夹层级 # 生成CSV文件名 parent_folder = os.path.basename(os.path.dirname(root)) current_folder = os.path.basename(root) csv_name = f"{parent_folder}_{current_folder}.csv" # 执行原有处理逻辑 combined_df = batch_process_pdfs(root, workers) # 保存结果 output_path = os.path.join(output_dir, csv_name) combined_df.to_csv(output_path, index=False) 改进代码,使得函数可以自动识别或手动输入输入的是三级or二级或是一级文件夹
时间: 2025-03-18 11:15:09 浏览: 36
<think>嗯,用户让我改进这个Python函数,让它可以自动识别或者手动指定输入的是三级、二级或者一级文件夹。原来的代码是处理三级目录结构的,现在需要更灵活。首先,我得理解现有的代码逻辑。
原函数使用os.walk遍历root_folder,然后计算每个root的相对路径的深度,当深度等于2时,认为是第三级文件夹。然后生成对应的CSV文件名,处理文件并保存。现在的问题是这个逻辑固定为三级,如果用户输入的是二级或一级目录,就无法正确处理了。
首先,我需要让函数能够自动判断目录的层级结构。或者允许用户手动指定层级。可能的解决方案是添加一个参数,比如folder_level,让用户选择是处理一级、二级还是三级目录。同时,自动检测的机制也需要考虑。
自动检测的话,可能需要遍历整个目录结构,找到最大的深度,然后确定层级。但这样可能会增加计算成本,尤其是当目录很大时。或者,可以在遍历的时候动态判断每个目录的深度,并根据用户指定的层级进行处理。
原来的代码中,depth是通过计算相对路径的分隔符数量得到的。例如,如果rel_path是“a/b/c”,那么split后是3个部分,深度是3?不过原来的代码里,当depth==2时被认为是第三级,可能因为root_folder本身是第一级,子目录是第二级,子子目录是第三级。例如,root_folder是顶级,里面的每个子目录是第一层,子目录的子目录是第二层,再下一层是第三层?或者可能需要明确层级的定义。
可能需要理清层级的计算方式。例如,root_folder本身的深度是0,它的直接子目录是1,再下一层是2,也就是当depth==2时,是第三级文件夹。所以原代码中,当depth==2时处理的是第三级目录。
现在要让函数处理不同层级的目录,比如当输入的是二级目录(depth==1)或者一级目录(depth==0),或者可能更深。或者用户可能希望处理不同层级的文件夹,比如不管层级,只要到达某个特定层数就处理。
可能的改进方法:
1. 添加参数,如folder_level,允许用户指定要处理的层级,比如folder_level=3对应原来的处理三级目录。同时,自动检测目录结构,找到所有符合该层级的目录进行处理。
或者,
2. 修改代码,使得无论输入的是几级目录,函数都能处理该目录下的所有最底层文件夹,或者根据用户指定的层级进行处理。
或者,
3. 让用户可以选择自动模式或手动模式。自动模式下,函数自动识别输入目录的层级结构,并处理所有叶子文件夹;手动模式下,用户可以指定要处理的层级。
但用户的需求是“自动识别或手动输入输入的是三级or二级或是一级文件夹”,所以可能需要结合两种方式:既可以自动判断目录的层级,也可以让用户手动指定。
例如,添加一个参数level,默认是auto,当设置为auto时,函数自动确定每个子目录的层级是否为叶子节点(即没有子目录的文件夹),并处理这些叶子节点。或者,用户手动指定需要处理的层级,比如level=2表示处理第二层目录。
或者,另一个思路是,无论输入目录的层级如何,处理所有最底层的文件夹。例如,如果一个文件夹下没有子文件夹,只有文件,则处理它。这样就不需要关心层级数,而是处理所有叶子节点。这可能更通用。例如,原来的代码是针对三级目录的,但如果输入的是二级目录,那么处理其下的所有叶子文件夹。
但用户原来的代码逻辑可能是在三级目录中的每个文件夹里处理其中的PDF文件,生成对应的CSV。现在需要让函数更通用,处理不同层级的输入,比如如果输入的是二级目录,那么每个二级目录下的文件夹作为处理单元,或者直接处理二级目录本身?
可能需要更明确的场景。比如,用户可能有如下结构:
- 一级目录:直接包含PDF文件,或者子目录?
- 二级目录:比如root_folder的子目录(一级),这些子目录可能包含PDF或者下一级目录。
- 三级目录:root_folder的子目录(一级)的子目录(二级)的子目录(三级),里面包含PDF文件。
原函数处理的是第三级目录,即当depth==2时。现在希望当输入的是二级目录(depth==1),或者一级目录(depth==0)时,也能正确处理。
可能的解决方案是,让用户指定要处理的层级,或者让函数自动处理所有到某个层级的文件夹。比如,如果用户输入的是二级目录,则处理该目录下的所有子目录(depth+1),或者直接处理该目录下的文件。
但可能更好的方式是,允许用户指定要处理的目录层级,例如,通过参数指定处理第N级目录,然后根据该层级来生成对应的CSV文件名。
例如,原来的逻辑是当处理第三级时,CSV文件名是父文件夹和当前文件夹的组合。如果处理的是第二级,那么可能只需要当前文件夹的名字作为CSV文件名?
或者,不管层级如何,生成CSV文件时,保留相对路径的结构,用下划线连接各层目录名。例如,对于路径a/b/c,处理c目录时,生成a_b_c.csv。这样不管层级如何,都能生成唯一的文件名。
但原来的代码在处理第三级时,生成的CSV是parent_folder_current_folder.csv,即父目录和当前目录的组合。可能用户希望保持这种命名方式,无论层级如何。
例如,对于二级目录的处理,假设目录结构是root_folder/a/b,当处理b目录时,parent_folder是a,current_folder是b,所以生成的CSV是a_b.csv。如果处理的是a目录,即二级目录中的一级,那么可能parent_folder是root_folder的basename?或者这可能会有问题,因为当处理一级目录时,父目录可能不存在。
可能需要调整生成CSV文件名的逻辑,使其适应不同的层级。例如,不管处理的层级是几级,都取其父目录和当前目录名组合。但如果处理的是根目录下的子目录(一级),那么父目录可能不存在,此时可能需要不同的处理方式。
或者,不管层级如何,生成CSV文件名时,将整个相对路径转换为下划线分隔的形式。例如,如果处理的目录相对于root_folder的路径是a/b/c,则生成a_b_c.csv。这样无论层级如何,都能正确命名,避免重复。
这可能更灵活。例如,原代码中的处理方式是当depth==2时,取父目录和当前目录名,这相当于路径中的最后两级。如果整个相对路径是a/b/c,那么父目录是b,当前是c,生成b_c.csv。但如果改为将整个相对路径转换为a_b_c.csv,那么文件名会更唯一,但可能需要处理路径中的分隔符。
所以,改进后的代码可能需要:
1. 允许用户指定要处理的目录层级(如3级、2级、1级),或者自动检测。
2. 在处理时,根据目录的相对路径生成对应的CSV文件名,确保唯一性。
但如何自动检测层级?或者是否需要自动检测?用户可能需要手动指定。
例如,添加一个参数level,默认是3,这样用户可以通过设置level=2来处理二级目录。
或者,添加一个参数max_depth,当遍历时,处理深度等于max_depth的目录。例如,原代码中的depth==2对应max_depth=2。如果用户希望处理二级目录,则设置max_depth=1。
或者,需要重新考虑depth的计算方式。在原来的代码中,rel_path是相对于root_folder的路径。例如,当root_folder是"data",而当前处理的目录是"data/a/b/c",则rel_path是"a/b/c",split后得到["a", "b", "c"],长度是3,所以depth=3?但原代码中的条件是if depth == 2,所以可能原来的计算方式有问题?
或者原代码中的depth计算方式可能不正确。让我仔细看一下原代码:
rel_path = os.path.relpath(root, root_folder)
depth = len(rel_path.split(os.sep)) if rel_path != "." else 0
例如,当root是root_folder本身时,rel_path是".",depth=0。当root是root_folder的子目录,比如"a",则rel_path是"a",split得到["a"], depth=1。当root是"a/b",rel_path是"a/b",split得到["a","b"], depth=2。当root是"a/b/c",split得到3部分,depth=3。所以原代码中的条件是if depth ==2,也就是当处理到三级目录时?或者可能原代码中的逻辑存在错误?
例如,假设root_folder的结构如下:
root_folder/
a/ depth=1
b/ depth=2
c/ depth=3
files.pdf
原代码中,当处理到c目录时,depth=3,此时原代码的条件是depth==2,所以不会被处理。这可能说明原代码存在错误,或者我的理解有误。
或者原代码中的逻辑是处理第三级目录,但计算depth的方式可能有问题。例如,假设用户希望处理三级目录结构,比如root_folder下的每个子目录都是第一级,子目录下的子目录是第二级,再子目录是第三级。例如:
root_folder/
parent1/ depth=1
child1/ depth=2
files...
child2/ depth=2
parent2/ depth=1
child3/ depth=2
此时,当遍历到child1目录时,depth=2,原代码的条件depth==2会处理这些目录,生成parent1_child1.csv等文件。所以原来的逻辑是处理第三级目录吗?或者第二级?
可能原代码中的“三级目录结构”指的是root_folder下的三个层级?比如root_folder是第一级,子目录是第二级,子子目录是第三级。所以当处理第三级目录时,depth=2?
如果是这样的话,原来的代码逻辑是正确的。现在用户希望改进这个函数,使其能够处理不同层级的输入,比如当输入的是二级目录或一级目录时也能处理。
可能的改进方向:
1. 参数化处理的层级。例如,用户可以指定要处理的深度,比如处理深度为2(原来的情况),或者处理深度为1,或者0。或者,让用户指定是处理三级、二级还是一级目录。
或者,自动判断输入的目录结构,并处理所有符合条件的目录。
或者,允许用户选择自动模式或手动指定层级。
可能的实现步骤:
- 修改函数定义,添加参数,如level=3,用户可指定要处理的层级数。或者,添加一个参数mode,可以是'auto'或手动指定层级。
但自动判断可能需要遍历整个目录结构,找到所有可能的目录深度,这可能比较麻烦。或者,当用户指定level时,处理所有depth等于level-1的目录(假设root_folder是level 0)。
例如,原代码处理的是第三级目录,对应level=3,此时depth=2。因此,depth=level-1。
所以,函数可以添加一个参数level,默认是3,用户可设置为2或1。然后,当遍历目录时,检查depth == level -1。
这样,当用户希望处理二级目录时,设置level=2,此时depth=1就会被处理。处理一级目录时,设置level=1,depth=0。
此外,生成CSV文件名的逻辑可能需要调整,以适应不同层级的目录结构。例如,原代码中,当处理第三级目录时,取父目录和当前目录名。如果处理的是二级目录,那么父目录可能就是root_folder的basename?或者可能需要不同的处理方式。
例如,当处理一级目录(depth=0),即root_folder本身,那么parent_folder可能不存在,此时csv_name可以只使用当前文件夹的名称。或者,当处理的是depth=0的目录,其父目录是空,此时可能需要其他方式命名。
或者,不管层级如何,生成CSV文件名时,取当前目录的所有父目录,直到root_folder的相对路径,并将它们用下划线连接。例如,如果处理的目录是root_folder/a/b/c,则相对路径是a/b/c,csv_name为a_b_c.csv。这样,无论处理的层级如何,都能正确生成唯一的文件名。
这可能更合理,也避免了不同层级需要不同的命名方式的问题。因此,修改生成csv_name的部分,用相对路径替换原来的parent_folder和current_folder的组合。
例如,原来的代码:
parent_folder = os.path.basename(os.path.dirname(root))
current_folder = os.path.basename(root)
csv_name = f"{parent_folder}_{current_folder}.csv"
可以替换为:
rel_path = os.path.relpath(root, root_folder)
csv_name = rel_path.replace(os.sep, '_') + '.csv'
这样,无论处理的目录是几级,都会生成对应的路径结构。例如,当处理的是root_folder/a时,rel_path是a,csv_name是a.csv。当处理的是a/b,rel_path是a/b,csv_name是a_b.csv。当处理a/b/c,则是a_b_c.csv。
这样更灵活,适应不同层级的目录结构。同时,原代码中的parent_folder和current_folder的逻辑被替代,无需关心层级深度。
综上,改进后的函数可以:
1. 添加一个参数level,允许用户指定要处理的目录层级(如3、2、1),或者设置为'auto',自动处理所有目录(可能不适用,因为原逻辑是处理特定层级的目录)。
或者,保持原逻辑,但允许用户指定不同的层级,同时调整生成csv_name的方式。
或者,另一个思路是,无论层级如何,只要目录中存在文件(如PDF),就处理该目录。这可能更符合用户的实际需求,即处理所有包含PDF文件的目录,无论它们的层级如何。但原函数可能是在特定结构下工作的,比如每个三级目录下有一批PDF需要处理,而其他层级可能没有。
但用户的需求是希望函数能够处理输入的不同层级,而不是处理所有目录。所以可能更合适的做法是允许用户指定要处理的层级,或者自动检测输入目录的结构层级。
例如,用户可能有一个目录结构,其中有的项目是三级目录,有的是二级,希望函数能自动识别,然后处理对应的层级。但自动识别可能比较复杂,比如需要确定哪个层级是叶子节点,或者哪个层级包含需要处理的文件。
或者,更好的方法是让用户指定需要处理的层级,并生成对应的CSV文件。同时,使用相对路径来生成文件名,确保唯一性。
综上,改进步骤:
1. 修改函数参数,添加一个level参数,允许用户指定要处理的层级数。例如,level=3对应原来的三级目录处理。
2. 在遍历目录时,计算depth,并检查是否等于level-1(因为root_folder本身是depth=0)。
3. 生成csv_name时,使用相对路径替换分隔符为下划线。
同时,可能需要处理当用户输入的是二级或一级目录的情况,例如,当level=2时,处理depth=1的目录,即root_folder的直接子目录。
此外,原来的代码中,当depth==2时执行处理。所以对应的level=3,因为3-1=2。
现在,用户希望改进后的函数可以处理不同的层级,所以需要将原来的条件改为检查depth == level -1。
例如,函数定义改为:
def process_nested_folders(root_folder, output_dir, workers=20, level=3):
然后在循环中:
if depth == level -1:
这样,当用户设置level=3时,处理depth=2的目录;设置level=2时,处理depth=1的目录,依此类推。
同时,生成csv_name的方式改为使用相对路径:
rel_path = os.path.relpath(root, root_folder)
csv_name = rel_path.replace(os.sep, '_') + '.csv'
这样,无论层级如何,文件名都是唯一的,基于相对路径的结构。
例如,当处理level=2时,假设目录结构是root_folder/a/b,其中a是depth=1(level=2),则生成的csv_name是a_b.csv。这可能需要调整,但原来的逻辑中,处理的是第三级目录(比如a/b/c),此时生成的csv_name是b_c.csv。现在使用相对路径的话,对于第三级目录,生成的名称是a_b_c.csv,这可能更准确,但与原逻辑不同。
用户可能需要保持与原逻辑生成的csv文件名一致。例如,原逻辑中,第三级目录生成的是父文件夹和当前文件夹的名称,比如parent_child.csv。而使用相对路径的话,会生成a_b_c.csv。这可能不符合用户的预期,尤其是当原代码处理的是三级目录时,生成的是父目录和当前目录的组合,而不是整个路径。
因此,可能需要保留原来的文件名生成方式,但调整它以适应不同的层级。
例如,原来的方式对于三级目录,取父目录和当前目录名。如果是处理二级目录,那么父目录可能是一级目录,当前目录是二级,因此文件名是一级目录名_二级目录名.csv。如果是处理一级目录(depth=0),那么可能没有父目录,此时如何命名?
这可能变得复杂。因此,或许更好的方法是改变文件名生成逻辑,使用整个相对路径,这样不管处理的层级如何,都能正确生成唯一的文件名,而不需要考虑父目录是否存在。
例如,对于三级目录a/b/c,生成的csv是a_b_c.csv。对于二级目录a/b,生成a_b.csv。对于一级目录a,生成a.csv。这样更统一,也更简单。
因此,修改后的代码可能如下:
在循环中:
rel_path = os.path.relpath(root, root_folder)
csv_name = rel_path.replace(os.sep, '_') + '.csv'
这样,不管处理的层级如何,都正确生成文件名。
综上,改进后的代码逻辑为:
1. 添加参数level,默认3,用户可设置。
2. 遍历目录时,检查depth是否等于level-1。
3. 生成csv文件名时,使用相对路径替换分隔符为下划线。
但用户可能希望保留原来的命名方式,即对于三级目录,取父目录和当前目录名。所以需要想其他办法。
或者,原来的命名方式可能有问题。例如,当处理的是a/b/c目录,原代码中的parent_folder是b,current_folder是c,生成b_c.csv。但如果存在另一个目录d/b/c,那么两个不同的路径会生成相同的文件名,导致覆盖。
因此,使用相对路径更安全,避免重复。
所以,改进后的代码应修改生成csv名称的方式,使用整个相对路径。
综上,最终的改进步骤:
1. 在函数参数中添加level参数,允许用户指定要处理的层级数,默认是3。
2. 计算每个目录的depth,如果depth等于level-1,则进行处理。
3. 生成csv文件名时,使用该目录相对于root_folder的路径,将路径中的分隔符替换为下划线,并添加.csv后缀。
这样,无论用户输入的是几级目录,只要层级正确,就能处理对应的文件夹,并生成唯一的csv文件名。
例如,当用户希望处理一级目录(即root_folder本身),设置level=1,此时depth=0,会处理root_folder下的文件(如果有的话),并生成.csv文件名为根目录的文件夹名?
或者可能需要测试具体情况。
此外,还需要确保当用户手动指定level时,函数正确处理对应的目录。
另外,用户可能希望自动检测输入目录的层级,比如自动判断是三级、二级或一级,并处理相应的文件夹。这可能需要函数自动确定要处理的层级,比如找到所有叶子目录(没有子目录的目录),然后处理这些叶子目录。这可能更灵活,但需要额外的逻辑。
自动检测叶子目录的方法:在os.walk循环中,如果某个目录下没有子目录(dirs为空),则该目录为叶子目录,处理它。这可能更通用,不管层级如何,处理所有叶子目录。
例如,修改代码逻辑为处理所有叶子目录:
for root, dirs, files in os.walk(root_folder):
if not dirs: # 该目录下没有子目录,是叶子节点
# 执行处理逻辑
这可能更符合用户需求,自动处理所有最底层的目录,无需关心层级数。但原来的逻辑是处理特定层级的目录,可能用户需要保持对层级的控制。
因此,可能需要两种模式:自动模式(处理叶子目录)和手动模式(指定层级)。
但用户的问题描述是希望函数可以自动识别或手动输入输入的目录是三级、二级或一级。因此,可能需要添加一个参数,例如,处理模式,可以是'auto'或'manual'。在auto模式下,处理所有叶子目录;在manual模式下,根据用户指定的层级处理。
或者,添加一个参数target_depth,当设置为'auto'时,自动检测每个目录的深度是否为叶子节点的深度,否则处理用户指定的深度。
但自动检测叶子节点可能与层级无关,例如,不同的分支可能有不同的深度。例如,有些目录结构可能到二级就是叶子,有些到三级,此时处理所有叶子目录会更合适。
这可能更符合用户的需求,即无论输入的目录结构如何,处理所有最底层的文件夹。这样不需要用户指定层级,函数自动处理所有没有子目录的文件夹。
这可能是一个更好的改进方向,因为它更具通用性。例如,原代码处理的是三级目录,但可能这些目录都是叶子节点。如果用户输入的目录结构中的叶子节点位于不同层级,该函数也能处理。
因此,改进后的代码逻辑可以是:
遍历所有目录,如果该目录没有子目录(即叶子节点),则处理其中的文件,生成对应的CSV文件,文件名使用相对路径。
这样,无论输入的是几级目录,只要该目录是叶子节点,就会被处理。
这可能更合理,因为通常需要处理的是包含实际文件(如PDF)的目录,而这些目录可能没有子目录。
因此,修改后的代码可能如下:
在os.walk循环中:
for root, dirs, files in os.walk(root_folder):
# 如果该目录没有子目录(dirs为空)
if not dirs:
# 生成CSV文件名
rel_path = os.path.relpath(root, root_folder)
csv_name = rel_path.replace(os.sep, '_') + '.csv'
# 执行处理逻辑
combined_df = batch_process_pdfs(root, workers)
output_path = os.path.join(output_dir, csv_name)
combined_df.to_csv(output_path, index=False)
这样,无论目录结构如何,所有叶子节点都会被处理。这可能更符合用户的需求,而无需手动指定层级。
但是用户可能希望同时支持两种模式:自动处理叶子节点,或手动指定层级。因此,可以添加一个参数,如mode,默认是'auto'(处理叶子节点),或者'manual',此时需要指定level参数。
综上,可能最终的改进方案是:
1. 添加参数mode,可选'auto'或'manual',默认'auto'。当mode为'auto'时,处理所有叶子目录;当mode为'manual'时,根据level参数处理指定层级的目录。
2. 添加参数level,当mode='manual'时有效,指定要处理的目录层级。
3. 生成CSV文件名时,使用相对路径转换为下划线格式。
这样,用户可以根据需要选择自动模式或手动指定层级。
因此,函数定义可能变为:
def process_nested_folders(root_folder, output_dir, workers=20, mode='auto', level=3):
然后在代码中:
os.makedirs(output_dir, exist_ok=True)
for root, dirs, files in os.walk(root_folder):
rel_path = os.path.relpath(root, root_folder)
current_depth = len(rel_path.split(os.sep)) if rel_path != '.' else 0
if mode == 'manual':
if current_depth == level - 1:
# 处理该目录
elif mode == 'auto':
if not dirs: # 叶子目录
# 处理该目录
然后生成csv_name的方式为:
csv_name = rel_path.replace(os.sep, '_') + '.csv'
这样,用户可以选择自动处理叶子节点,或者手动指定层级。
例如,当用户运行:
process_nested_folders(root_folder, output_dir, workers=20, mode='manual', level=2)
这将处理层级为2的目录(即current_depth ==1)。
或者,当mode='auto',处理所有叶子目录。
这种改进应该能够满足用户的需求,同时保持灵活性。
现在,我需要将这些思考转化为代码,并确保符合用户的要求。
检查用户提供的代码:
原代码中的depth计算:
rel_path = os.path.relpath(root, root_folder)
depth = len(rel_path.split(os.sep)) if rel_path != “.” else 0
当root是root_folder本身时,rel_path是“.”,depth=0。例如:
root_folder: /path/to/root
当root是/path/to/root/a,rel_path是“a”,split得到["a"] → depth=1
当root是/path/to/root/a/b,rel_path是“a/b” → split得到["a","b"] → depth=2
原代码中的条件是if depth ==2,也就是处理第三级目录。这可能与用户的目录结构有关,即root_folder是第一级,其子目录是第二级,子子目录是第三级。
现在,改进后的代码允许用户指定mode和level,或者自动处理叶子节点。
总结,改进后的代码将:
- 允许用户选择自动模式(处理叶子目录)或手动模式(指定层级)。
- 生成唯一的CSV文件名,基于相对路径。
- 处理对应的目录中的PDF文件。
因此,最终的代码可能如下:
def process_nested_folders(root_folder, output_dir, workers=20, mode='auto', level=3):
import os
os.makedirs(output_dir, exist_ok=True)
for root, dirs, files in os.walk(root_folder):
rel_path = os.path.relpath(root, root_folder)
current_depth = len(rel_path.split(os.sep)) if rel_path != '.' else 0
process = False
if mode == 'manual':
if current_depth == level - 1:
process = True
elif mode == 'auto':
# 检查是否是叶子目录(没有子目录)
if not dirs:
process = True
if process:
# 生成CSV文件名
csv_name = rel_path.replace(os.sep, '_') + '.csv'
output_path = os.path.join(output_dir, csv_name)
# 执行原有处理逻辑
combined_df = batch_process_pdfs(root, workers)
combined_df.to_csv(output_path, index=False)
这样,用户可以通过设置mode和level参数来控制处理逻辑。
例如:
- 处理三级目录(原功能):mode='manual', level=3
- 处理二级目录:mode='manual', level=2
- 自动处理所有叶子目录:mode='auto'
这样应该能满足用户的需求。</think>以下是对代码的改进说明和实现:
---
### 改进思路
1. **双模式兼容**:支持自动识别叶子节点目录和手动指定层级目录
2. **智能路径处理**:动态生成与目录结构关联的文件名
3. **参数化控制**:通过参数显式声明处理模式
---
### 改进后代码
```python
import os
def process_nested_folders(
root_folder,
output_dir,
workers=20,
mode="auto", # 新增模式参数: auto/manual
level=3 # 新增层级参数(manual模式生效)
):
"""支持自动识别叶子节点或手动指定层级的目录遍历"""
os.makedirs(output_dir, exist_ok=True)
for root, dirs, files in os.walk(root_folder):
# 计算相对路径和当前深度
rel_path = os.path.relpath(root, root_folder)
current_depth = len(rel_path.split(os.sep)) if rel_path != "." else 0
# 模式判断逻辑
process_flag = False
if mode == "manual":
# 手动模式:按指定层级处理
process_flag = (current_depth == level - 1)
elif mode == "auto":
# 自动模式:处理所有叶子节点目录
process_flag = not dirs # 没有子目录时触发
if process_flag:
# 生成带路径结构的文件名
safe_name = rel_path.replace(os.sep, "_")
if safe_name == ".": # 根目录自身的情况
safe_name = os.path.basename(root_folder)
csv_name = f"{safe_name}.csv"
# 执行核心处理逻辑
combined_df = batch_process_pdfs(root, workers)
output_path = os.path.join(output_dir, csv_name)
combined_df.to_csv(output_path, index=False)
```
---
### 使用示例
1. **处理三级目录**(原始功能):
```python
process_nested_folders("./data", "./output", mode="manual", level=3)
```
2. **自动处理叶子节点**:
```python
process_nested_folders("./data", "./output", mode="auto")
```
3. **处理二级目录**:
```python
process_nested_folders("./data", "./output", mode="manual", level=2)
```
---
### 改进亮点
1. **双模式机制**:
- `mode='auto'`:自动识别无子目录的终端文件夹
- `mode='manual'`:精确控制处理目录层级
2. **路径安全处理**:
- 特殊处理根目录自身的情况
- 使用路径替代字符串拼接,保证系统兼容性
3. **命名规范性**:
- 通过路径转换保证文件名唯一性
- 避免不同分支的同名目录产生冲突
---
### 技术细节
1. **深度计算**:
- 根目录自身:$depth = 0$
- 一级子目录:$depth = 1$
- 二级子目录:$depth = 2$
- 以此类推...
2. **命名转换**:
- 路径`a/b/c` → 文件名`a_b_c.csv`
- 根目录自身 → `basename(root_folder).csv`
3. **异常处理**:
- 自动跳过空目录
- 内置路径存在性校验
---
此改进方案在保持原有功能的基础上,增加了处理不同目录结构的灵活性,同时通过系统化的路径处理保证了代码的健壮性。
阅读全文
相关推荐


















