【问题标题】:Python os.walk and symlinksPython os.walk 和符号链接
【发布时间】:2016-04-08 13:22:40
【问题描述】:

在修复一个用户的 answer on AskUbuntu 时,我发现了一个小问题。代码本身很简单: os.walk ,递归获取目录中所有文件的总和。

但它会在符号链接上中断:

$ python test_code2.py $HOME                                                                                          
Traceback (most recent call last):
  File "test_code2.py", line 8, in <module>
    space += os.stat(os.path.join(subdir, f)).st_size
OSError: [Errno 2] No such file or directory: '/home/xieerqi/.kde/socket-eagle'

那么问题是,我如何告诉 python 忽略这些文件并避免对它们求和?

解决方案

按照 cmets 中的建议,我添加了 os.path.isfile() 检查,现在它可以完美运行并为我的主目录提供正确的大小

$> cat test_code2.py                                                          
#! /usr/bin/python
import os
import sys

space = 0L  # L means "long" - not necessary in Python 3
for subdir, dirs, files in os.walk(sys.argv[1]):
    for f in files:
        file_path = os.path.join(subdir, f)
        if os.path.isfile(file_path):
           space += os.stat(file_path).st_size

sys.stdout.write("Total: {:d}\n".format(space))
$> python test_code2.py  $HOME                                                
Total: 76763501905

【问题讨论】:

  • 它不会在符号链接上中断。它在 broken 符号链接上中断。在任何情况下,您都可以使用os.path.isfile 测试文件名是否指向实际文件,然后再对其大小求和。
  • 啊哈,敏锐,这就是代码在我的测试中有效的原因:)
  • @AnttiHaapala 那么解决方案应该是什么?删除损坏的符号链接?有没有办法在代码本身中解决这个问题?
  • 只测试文件是否存在,如果不存在则跳过。
  • @AnttiHaapala 发布答案:)

标签: python symlink


【解决方案1】:

正如 Antti Haapala 在评论中已经提到的,脚本不会在符号链接上中断,而是在损坏的符号链接上。避免这种情况的一种方法是以现有脚本为起点,使用try/except

#! /usr/bin/python2
import os
import sys

space = 0L  # L means "long" - not necessary in Python 3
for root, dirs, files in os.walk(sys.argv[1]):
    for f in files:
        fpath = os.path.join(root, f)
        try:
            space += os.stat(fpath).st_size
        except OSError:
            print("could not read "+fpath)

sys.stdout.write("Total: {:d}\n".format(space))

作为副作用,它会为您提供有关可能损坏的链接的信息。

【讨论】:

  • UPV 但你不是在 AU 告诉我你从不使用 Python 2 吗?)
【解决方案2】:

是的,os.path.isfile 是要走的路。然而,以下版本可能内存效率更高。

for subdir, dirs, files in os.walk(sys.argv[1]):
    paths = (os.path.join(subdir, f) for f in files)
    space = sum(os.stat(path).st_size for path in paths if os.path.isfile(path))

【讨论】:

  • 有趣,为什么 sum() 的内存效率更高?
  • @Serg 不是sum,是迭代器的使用导致了空间效率。可以看到paths 是一个基因表达式。因此,这种声明式风格可确保您一次处理 一个 对象,同时实质上同时讨论 all。没有中间容器数据结构。但是在这个例子中,我使用了“may be”,正如你所看到的,因为无论如何都没有中间列表。但有一个副作用,space 正在改变。
  • 这段代码肯定更紧凑,但我不明白它是如何节省内存的。也许随着我对 Python 的了解更多,我会更好地理解您对@SergiyKolodyaznyy 的回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-13
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多