Python初学问题6

版权声明:欢迎转载,但是请标明文章作者和出处。 https://blog.csdn.net/handsomehuo/article/details/90544777

问题描述:os.path.isdir() 和os.path.isfile()在第二层循环的时候出现判断错误。

问题代码:

#编写一个程序,能在当前目录以及当前目录的所有子目录下查找文件名包含指定字符串的文件,并打印出相对路径。
import os
def findfile(name, path):
        for file in os.listdir(path):
            print(file)
            print(os.path.abspath(file))
            if os.path.isdir(file):
                newpath = os.path.abspath(file)
                findfile(name, newpath)
            else:
                if name in file:
                    a = os.path.abspath(file)
                    print(a)
                    print('文件名是%s' % os.path.split(a)[1], '地址是%s' % os.path.split(a)[0])

通过调试我们发现,这个recursion程序本身并没有报错,但是如果遇到这样一个场景:A文件夹包含B,B包含C,函数在执行到C层面后,即使有file,也会被内置函数os.path.isdir()判断为false,非常诡异。

好在我们做了2个print输出,可以观察路径,通过运行我们发现,路径不对!

比如文件如果是在/A/B/C/1234.txt,当file为1234.txt时,os.path.abspath(file)的输出居然是/A/1234.txt,导致os.path.isdir()根本找不到这个文件,从而返回一个OSError。

因此问题是出在os.path.abspath()这个函数上的,它一直返回的是函数的执行地址+文件名,非常敷衍!所以表面上看是os.path.isdir()的问题,但其实是错怪他了。

看一下abspath的代码,一目了然。

def abspath(path):
    """Return an absolute path."""
    path = os.fspath(path)
    if not isabs(path): #判断是否是绝对路径,经判断不是绝对路径
        if isinstance(path, bytes): 
            cwd = os.getcwdb()
        else:
            cwd = os.getcwd()#返回函数当前执行路径
        path = join(cwd, path)
    return normpath(path)

那么接下来延伸的问题是,为什么isabs(path)会是false呢,原因出在另一个函数上:os.listdir(path)。

看一下关于os.listdir(path)的官方解释

Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order, and does not include the special entries '.' and '..' even if they are present in the directory.

返回处'.'和'..'外的给定路径的所有文件和目录名的按字母顺序排序的列表。

...

The scandir() function returns directory entries along with file attribute information, giving better performance for many common use cases.

scandir()函数返回带有属性的文件和目录路径,在很多场景下有更好的使用效果。

明白了,os.listdir(path)只返回带字符串的列表,不带属性,不管路径的真实性,官方推荐我们使用scandir()。

因此,这段代码应该怎么修改呢?

有三种方法:

1、使用os.walk,不用自造轮子。

2、使用os.scandir()替换os.listdir()。

3、用chdir()更换目录执行路径。

...
os.chdir(file)
newpath = os.path.abspath('.')
print(newpath)
...
os.chdir(os.path.abspath('..'))

猜你喜欢

转载自blog.csdn.net/handsomehuo/article/details/90544777