Python: os.stat ().размер st дает другое значение, чем du
Я создаю утилиту, которая будет проходить через каталоги и получать размеры дочерних каталогов и файлов для всех каталогов и хранить значение. Однако размеры вычисляются неправильно.
вот, что автоматически повторяется через все подкаталоги:class directory:
    '''
    Class that automatically traverses directories
    and builds a tree with size info
    '''
    def __init__(self, path, parent=None):
        if path[-1] != '/':
            # Add trailing /
            self.path = path + '/'
        else:
            self.path = path
        self.size = 4096
        self.parent = parent
        self.children = []
        self.errors = []
        for i in os.listdir(self.path):
            try:
                self.size += os.lstat(self.path + i).st_size
                if os.path.isdir(self.path + i) and not os.path.islink(self.path + i):
                    a = directory(self.path + i, self)
                    self.size += a.size
                    self.children.append(a)
            except OSError:
                self.errors.append(path + i)
у меня есть каталог видео, которые я тестирую эту программу с:
>>> a = directory('/var/media/television/The Wire')
>>> a.size
45289964053
однако, когда я пытаюсь то же самое с du, я получаю
$ du -sx /var/media/television/The Wire
44228824
в каталоги не содержат ссылок или чего-то особенного.
может кто-нибудь объяснить, почему os.stat() дает странные показания размера?
- Linux (Fedora 13)
 - Python 2.7
 
4 ответов
рассмотрим этот файл foo
-rw-rw-r-- 1 unutbu unutbu 25334 2010-10-31 12:55 foo
Он состоит из 25334 байт.
tune2fs говорит мне, что foo находится в файловой системе с размером блока 4096 байт:
% sudo tune2fs -l /dev/mapper/vg1-OS1
...
Block size:               4096
...
таким образом, самый маленький файл в файловой системе будет занимать 4096 байт, даже если его содержимое состоит всего из 1 байта. По мере увеличения файла пространство выделяется в 4096-байтовых блоках.
du reports
% du -B1 foo
28672   foo
обратите внимание, что 28672/4096 = 7. Это говорит о том, что Foo оккуписа 7 4096-байтовых блоков в файловой системе. Это наименьшее количество блоков, необходимых для хранения 25334 байт.
% du foo
28  foo
эта версия du просто сообщает 28672/1024 округлено вниз.
du дает размер на диске по умолчанию, по сравнению с фактическим размером файла, как указано в st_size.
$ du test.txt
    8    test.txt
$ du -b test.txt
    6095 test.txt
>>> os.stat('test.txt').st_size
6095
Я бы написал этот код:
import os, os.path
def size_dir(d):
    file_walker = (
        os.path.join(root, f)
        for root, _, files in os.walk(d)
        for f in files
    )
    return sum(os.path.getsize(f) for f in file_walker)
Если вы хотите считать каталоги как 4k, то сделайте что-то вроде этого:
import os, os.path
def size_dir(d):
    file_walker = (
        os.path.join(root, f)
        for root, _, files in os.walk(d)
        for f in files
    )
    dir_walker = (
        4096
        for root, dirs, _ in os.walk(d)
        for d in dirs
    )
    return 4096 + sum(os.path.getsize(f) for f in file_walker) + sum(size for size in dir_walker)
в linux (я использую CentOS),' du-b ' вернется в байтах и активирует --apparent-size таким образом, возвращая размер файла, а не объем дискового пространства, которое он использует. Попробуйте это и посмотрите, согласуется ли это с тем, что Python os.stat говорит.