Python面试题系列之05: 设计实现遍历目录及子目录,并抓取.txt文件?
Question
设计实现遍历目录及子目录,并抓取.txt文件?
知识点详解
这道题并不难,这里我们用三种思路来实现这个小需求。依次会用到os模块、glob模块、pathlib模块。
方法一:利用os模块
python的os库有很多和文件,路径,执行系统命令相关的功能。比如我们可以使用os.listdir()方法来列出目录下的所有文件和目录放入一个列表进行返回,但是listdir()函数不可对目录的子目录进行扫描。
很多时候我们需要将某个文件夹下的所有文件都要找出来,那么此时我们就需要os.walk()。它通过在目录树中向下或向上游走,输出目录的文件名。
os.walk()方法的语法格式如下:
os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
- top – 是你所要遍历的目录的地址
- topdown –可选,为 True,则优先遍历 top 目录,否则优先遍历 top 的子目录。
- onerror – 可选,需要一个 callable 对象,当 walk 需要异常时,会调用。
- followlinks – 可选,若为 True,则会遍历目录下的快捷方式。
该函数没有返回值,会使用yield关键字抛出一个存放当前该层目录(dirpath, dirnames, filenames)的三元组,最终将所有目录层的的结果变为一个生成器。
- dirpath是一个
string,代表目录的路径; - dirnames是一个
list,包含了dirpath下所有子目录的名字; - filenames是一个
list,包含了非目录文件的名字。这些名字不包含路径信息,如果需要得到全路径,需要使用 os.path.join(dirpath, filename);
了解了os.walk的语法后,接下来直接上代码,来实现这个需求。
import os
def get_files(dir, suffix):
res = []
for dirpath,dirnames,filenames in os.walk(dir):
for filename in filenames:
name, suf = os.path.splitext(filename)
if suf == suffix:
res.append(os.path.join(dirpath, filename))
print(res)
get_files("E:\Pythonista", '.txt')
方法二:利用glob模块
glob模块可以使用Unix shell风格的通配符匹配符合特定格式的文件和文件夹,跟windows的文件搜索功能差不多。glob模块并非调用一个子shell实现搜索功能,而是在内部调用了os.listdir()和fnmatch.fnmatch()。
glob模块支持的通配符如下:
*匹配0或多个字符**匹配所有文件、目录、子目录和子目录里的文件(Python 3.5版本新增)?匹配1个字符,与正则表达式里的?不同[exp]匹配指定范围内的字符,如:[1-9]匹配1至9范围内的字符[!exp]匹配不在指定范围内的字符
接下来就利用glob模块来实现这个需求,以下是具体代码:
from glob import iglob
def func(filepath, suffix):
for i in iglob(f"{filepath}/**/*{suffix}", recursive=True):
print(i)
if __name__ == "__main__":
suffix = ".txt"
func("E:\Pythonista", suffix)
自从Python 3.5版本新增了**通配符,glob模块变得更加易用,真是太赞了😉
方法三:利用pathlib模块
pathlib模块是Python 3.4版本中新增的模块,pathlib绝不仅仅是替换了os.path那么简单,它可以说是路径处理的瑞士军刀。它完全采用面向对象的编程方式,尤其是在处理配置路径方面简直太方便了。
闲话少说,我们直接用Path().rglob来递归遍历指定的文件。
from pathlib import Path
src = "E:\Pythonista"
for item in Path(src).rglob('*.txt'):
print(item)
简单几行代码,轻松搞定😎
Answer
无论用os模块、还是glob模块、或是pathlib模块均可实现这一需求,详细代码见上文内容。
后记
上述三种方法都能实现这一需求,但哪种方法更加简便已不言而喻。所以还是希望大家能多了解一些Python新版本的特性,紧跟技术前沿😁😁😁
可通过如下这个链接来了解Python 3中每个版本加入的新特性。
https://docs.python.org/3.x/whatsnew/3.x.html
注:需要把x替换成实际版本号即可。好了,以上就是本篇全部内容。
备注:本篇首发于知识星球「人人都是Pythonista」。