Python os.walk и символические ссылки

Исправляя ответ одного пользователя на 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 игнорировать эти файлы и не суммировать их?

Решение:

Как предложено в комментариях, я добавил 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

2 ответа

Решение

Как уже упоминал Антти Хаапала в комментарии, скрипт не разбивается на символические ссылки, а на битые символические ссылки. Одним из способов избежать этого, взяв существующий сценарий в качестве отправной точки, является использование 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))

Как побочный эффект, он дает вам информацию о возможных неработающих ссылках.

Да, 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))
Другие вопросы по тегам