Как я могу проверить размер файла в Python?

760

Я пишу сценарий Python в Windows. Я хочу сделать что-то в зависимости от размера файла. Например, если размер больше 0, я отправлю электронное письмо кому-либо, в противном случае перейду к другим вещам.

Как проверить размер файла?

5YrsLaterDBA
источник
2
Path('./doc.txt').stat().st_size
Борис
Спасибо @Boris за современный ответ Python (v3.4 +) :)
mab

Ответы:

737

Вам нужно st_sizeсвойство возвращаемого объектаos.stat . Вы можете получить его, используя pathlib(Python 3.4+):

>>> from pathlib import Path
>>> Path('somefile.txt').stat()
os.stat_result(st_mode=33188, st_ino=6419862, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=1564, st_atime=1584299303, st_mtime=1584299400, st_ctime=1584299400)
>>> Path('somefile.txt').stat().st_size
1564

или используя os.stat:

>>> import os
>>> os.stat('somefile.txt')
os.stat_result(st_mode=33188, st_ino=6419862, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=1564, st_atime=1584299303, st_mtime=1584299400, st_ctime=1584299400)
>>> os.stat('somefile.txt').st_size
1564

Вывод в байтах.

Адам Розенфилд
источник
2
Во всяком случае, значение может быть передано как кратное размеру блока файловой системы (например, 4096 байт). К счастью, оно дается в байтах.
josch
1
@josch - да, это хорошо, для «размера на диске» вы можете умножить stat_result.st_blocksна размер блока, но я все еще ищу, как получить его программно и кроссплатформенно (не через tune2fsи т. д.)
Томас Гандор
1101

Использование os.path.getsize:

>>> import os
>>> b = os.path.getsize("/path/isa_005.mp3")
>>> b
2071611

Вывод в байтах.

danben
источник
125
Примечание: реализация os.path.getsizeпростоreturn os.stat(filename).st_size
Вим
Итак, есть ли потеря производительности при использовании os.path.getsize, а не os.stat (file) .st_size?
словами
5
@wordsforthewise измерить это! ~ 150 нс в моем компьютере.
Davidmh
@words, потому что это больше проблема, если вы также хотите получить другие сведения о файле (время изменения, тип файла и т. д.) - тогда вы можете получить все это с помощью одного системного вызова через os.stat. Тогда разница может составить значительное количество микросекунд :-)
greggo
Если это называется право после того, как файл создан , он возвращает 0 @danben
Alper
131

Другие ответы работают для реальных файлов, но если вам нужно что-то, что работает для «файловых объектов», попробуйте это:

# f is a file-like object. 
f.seek(0, os.SEEK_END)
size = f.tell()

Это работает для реальных файлов и StringIO, в моем ограниченном тестировании. (Python 2.7.3.) API "file-like object", конечно, не совсем строгий интерфейс, но документация API предполагает, что file-like объекты должны поддерживать seek()и tell().

редактировать

Еще одно различие между этим и тем os.stat(), что вы можете stat()файл, даже если у вас нет разрешения на его чтение. Очевидно, что подход поиска / сообщения не будет работать, если у вас нет разрешения на чтение.

Редактировать 2

По предложению Джонатона, вот параноидальная версия. (Приведенная выше версия оставляет указатель файла в конце файла, поэтому, если вы попытаетесь прочитать файл, вы получите ноль байтов назад!)

# f is a file-like object. 
old_file_position = f.tell()
f.seek(0, os.SEEK_END)
size = f.tell()
f.seek(old_file_position, os.SEEK_SET)
Марк Э. Хаас
источник
8
Вам не нужно импортировать os, вместо этого пишите, f.seek(0, 2)чтобы искать 0 байтов с конца.
cdosborn
2
И для последней строки, если osне используется:f.seek(old_file_position, 0)
luckydonald
48
Если вы используете целочисленные литералы вместо именованных переменных, вы мучаете любого, кто должен поддерживать ваш код. Там нет веских причин, чтобы не импортировать os.
Марк Э. Хааз
Спасибо за решение, я реализовал, и он работает нормально. Просто чтобы подтвердить, sizeвывод в байтах?
Kedar.Aitawdekar
3
Видимо, это немного рискованно, в зависимости от того, как Python реализует #seek(): wiki.sei.cmu.edu/confluence/display/c/…
Autumnsault
72
import os


def convert_bytes(num):
    """
    this function will convert bytes to MB.... GB... etc
    """
    for x in ['bytes', 'KB', 'MB', 'GB', 'TB']:
        if num < 1024.0:
            return "%3.1f %s" % (num, x)
        num /= 1024.0


def file_size(file_path):
    """
    this function will return the file size
    """
    if os.path.isfile(file_path):
        file_info = os.stat(file_path)
        return convert_bytes(file_info.st_size)


# Lets check the file size of MS Paint exe 
# or you can use any file path
file_path = r"C:\Windows\System32\mspaint.exe"
print file_size(file_path)

Результат:

6.1 MB
Раджив Шарма
источник
5
this function will convert bytes to MB.... GB... etcНеправильно. Эта функция преобразует байты в MiB, GiB и т. Д. Смотрите этот пост .
Moi
2
Строка 10 может быть изменена на return f'{num:.1f} {x}'Python> = 3.5.
Мэтт М.
53

Использование pathlib( добавлено в Python 3.4 или бэкпорт доступен на PyPI ):

from pathlib import Path
file = Path() / 'doc.txt'  # or Path('./doc.txt')
size = file.stat().st_size

На самом деле это всего лишь интерфейс os.stat, но использование pathlibобеспечивает простой способ доступа к другим операциям, связанным с файлами.

pumazi
источник
18

Есть bitshiftхитрость, которую я использую, если хочу преобразовать из bytesлюбого другого устройства. Если вы делаете правильный сдвиг, 10вы в основном сдвигаете его на порядок (кратно).

Пример: 5GB are 5368709120 bytes

print (5368709120 >> 10)  # 5242880 kilobytes (kB)
print (5368709120 >> 20 ) # 5120 megabytes (MB)
print (5368709120 >> 30 ) # 5 gigabytes (GB)
user1767754
источник
9
Это не отвечает на вопрос. Вопрос заключается в том, чтобы найти размер файла, а не в форматировании результата для потребления человеком.
Уилл Мэнли
1
Эти цифры неверны и поэтому сбивают с толку. 5 ГБ - это 5e9 байтов. Это должно быть какое-то удобочитаемое приближение? Где бы вы использовали что-то подобное?
Dre
1-бит => 2 ... 2-бит => 4 ... 3-бит => 8 ... 4-бит => 16 ... 5-бит => 32 ... 6-бит => 64 ... 7 бит => 128 ... 8 бит => 256 ... 9 бит => 512 ... 10 бит => 1024 ... 1024 байта - 1 кБ ... => 20 -биты => 1024 * 1024 = 1 048 576 байт, что составляет 1024 КБ, и 1 МБ ... => 30 битов => 1024 * 1024 * 1024 = 1 073 741 824 байт, что составляет 1 048 576 КБ, и 1024 МБ, и 1 ГБ… Вы запутались научная запись и десятичные разряды с двоичным представлением / представлением base-2, используемым в вычислениях. 5x9 = 5 x 10 ^ 9 = 5 000 000 000
Джеймс «Пушистый» Бертон
3
Ребята, он ничего не перепутал ... ему просто дали приближение, что видно, когда он говорит "в основном". 2 ^ 10 составляет ок. 10 ^ 3. На самом деле, это приближение настолько распространено, что имеет название : Mebi , Gibi и Tebi - Mega, Giga и Tera соответственно. Что касается ответа на вопрос, @WillManley, у вас есть справедливое мнение! ;-p
Майк Уильямсон
9

Строго придерживаясь этого вопроса, код Python (+ псевдокод) будет:

import os
file_path = r"<path to your file>"
if os.stat(file_path).st_size > 0:
    <send an email to somebody>
else:
    <continue to other things>
Виктор Баррантес
источник
-1
#Get file size , print it , process it...
#Os.stat will provide the file size in (.st_size) property. 
#The file size will be shown in bytes.

import os

fsize=os.stat('filepath')
print('size:' + fsize.st_size.__str__())

#check if the file size is less than 10 MB

if fsize.st_size < 10000000:
    process it ....
Чикку Джейкоб
источник
-1

у нас есть два варианта Оба включают импорт модуля ОС

1) import os как функция os.stat () возвращает объект, который содержит так много заголовков, включая время создания файла, время последнего изменения и т. Д. Среди них st_size () дает точный размер файла.

os.stat ( "имя_файла"). st_size ()

2) import os Здесь мы должны указать точный путь к файлу (абсолютный путь), а не относительный путь.

os.path.getsize ("путь к файлу")

gunarevuri
источник