Jak mogę sprawdzić rozmiar pliku w Pythonie?

757

Piszę skrypt w języku Python w systemie Windows. Chcę zrobić coś na podstawie rozmiaru pliku. Na przykład, jeśli rozmiar jest większy niż 0, wyślę do kogoś wiadomość e-mail, w przeciwnym razie przejdź do innych rzeczy.

Jak sprawdzić rozmiar pliku?

5YrsLaterDBA
źródło
2
Path('./doc.txt').stat().st_size
Boris
Dzięki @ Boris za nowoczesną odpowiedź na Python (v3.4 +) :)
mab

Odpowiedzi:

734

Potrzebujesz st_sizewłaściwości obiektu zwróconego przezos.stat . Możesz go uzyskać za pomocą 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

lub używając 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

Dane wyjściowe są w bajtach.

Adam Rosenfield
źródło
2
Jeśli już, wartość można przekazać jako wielokrotność wielkości bloku systemu plików (na przykład 4096 bajtów). Chętnie zamiast tego jest podawany jako bajty.
josch
1
@josch - tak, to fajnie, bo „rozmiar na dysku” można pomnożyć stat_result.st_blocksprzez rozmiar bloku, ale wciąż szukam, jak uzyskać go programowo i na różnych platformach (nie za pośrednictwem tune2fsitp.)
Tomasz Gandor
1097

Używanie os.path.getsize:

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

Dane wyjściowe są w bajtach.

Danben
źródło
124
Uwaga: wdrożenie os.path.getsizejest po prostureturn os.stat(filename).st_size
wim
Czy jest więc niewielka utrata wydajności przy użyciu os.path.getsize w przeciwieństwie do os.stat (plik) .st_size?
słowa
5
@wordforthewise zmierzyć to! ~ 150 ns na moim komputerze.
Davidmh
@ słowa, w przeciwnym razie jest to większy problem, jeśli chcesz uzyskać inne informacje na temat pliku (czas modyfikacji, typ pliku, np.) - wtedy równie dobrze możesz uzyskać wszystko z jednego wywołania systemowego za pośrednictwem os.stat. Różnica może wtedy
spaść
Jeśli zostanie wywołany bezpośrednio po utworzeniu pliku, zwraca 0 @danben
alper
131

Inne odpowiedzi działają dla prawdziwych plików, ale jeśli potrzebujesz czegoś, co działa dla „obiektów podobnych do plików”, spróbuj tego:

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

W moich ograniczonych testach działa dla prawdziwych plików i StringIO. (Python 2.7.3.) Interfejs API „obiektopodobny” nie jest tak naprawdę rygorystycznym interfejsem, ale dokumentacja API sugeruje, że obiekty podobne do plików powinny obsługiwać seek()i tell().

Edytować

Kolejna różnica między tym a os.stat()tym, że możesz stat()utworzyć plik, nawet jeśli nie masz pozwolenia na jego odczytanie. Oczywiście podejście „szukaj / mów” nie będzie działać, chyba że masz uprawnienia do odczytu.

Edytuj 2

Według sugestii Jonathona, oto wersja paranoiczna. (Powyższa wersja pozostawia wskaźnik pliku na końcu pliku, więc jeśli spróbujesz odczytać z pliku, otrzymasz z powrotem zero bajtów!)

# 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)
Mark E. Haase
źródło
8
Nie musisz importować os, zamiast tego napisz, f.seek(0, 2)aby wyszukać 0 bajtów od końca.
cdosborn
2
I dla ostatniego wiersza, jeśli osnie jest używany:f.seek(old_file_position, 0)
luckydonald
48
Jeśli używasz literałów całkowitych zamiast nazwanych zmiennych, torturujesz każdego, kto musi utrzymywać twój kod. Nie ma ważnego powodu, aby nie importować os.
Mark E. Haase,
Dzięki za rozwiązanie, które zaimplementowałem i działa dobrze. Żeby tylko potwierdzić, sizewyjście jest w bajtach?
Kedar.Aitawdekar
3
Najwyraźniej jest to co najmniej trochę ryzykowne, w zależności od tego, jak Python implementuje #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)

Wynik:

6.1 MB
Rajiv Sharma
źródło
5
this function will convert bytes to MB.... GB... etcŹle. Ta funkcja konwertuje bajty na MiB, GiB itp. Zobacz ten post .
moi
2
Wiersz 10 można zmienić na return f'{num:.1f} {x}'w Pythonie> = 3.5.
Matt M.
53

Za pomocą pathlib( dodany w Python 3.4 lub backport dostępny w PyPI ):

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

W rzeczywistości jest to tylko interfejs os.stat, ale korzystanie z niego pathlibzapewnia łatwy dostęp do innych operacji związanych z plikami.

pumazi
źródło
18

Jest pewien bitshiftpodstęp, którego używam, jeśli chcę przekonwertować z bytesdowolnej innej jednostki. Jeśli wykonasz właściwą zmianę, 10po prostu przesuń ją o kolejność (wielokrotność).

Przykład: 5GB are 5368709120 bytes

print (5368709120 >> 10)  # 5242880 kilobytes (kB)
print (5368709120 >> 20 ) # 5120 megabytes (MB)
print (5368709120 >> 30 ) # 5 gigabytes (GB)
użytkownik1767754
źródło
9
To nie odpowiada na pytanie. Pytanie dotyczy znalezienia rozmiaru pliku, a nie sformatowania wyniku do spożycia przez ludzi.
Will Manley,
1
Te liczby są błędne, a zatem mylące. 5 GB to 5e9 bajtów. Czy to ma być jakieś czytelne dla człowieka przybliżenie? Gdzie w ogóle użyłbyś czegoś takiego?
Dre
1-bit => 2 ... 2-bity => 4 ... 3-bity => 8 ... 4-bity => 16 ... 5-bitów => 32 ... 6-bit = 64 ... 7-bitów => 128 ... 8-bitów => 256 ... 9-bitów => 512 ... 10-bitów => 1024 ... 1024 bajtów to 1kB ... => 20 -bity => 1024 * 1024 = 1 048 576 bajtów, czyli 1024 kB i 1 MB ... => 30-bitów => 1024 * 1024 * 1024 = 1 073 741 824 bajtów, co stanowi 1 048 576 kB i 1024 MB, a 1 GB… Myliłeś się notacja naukowa i miejsca dziesiętne z reprezentacją binarną / base-2 używaną w obliczeniach. 5x9 = 5 x 10 ^ 9 = 5 000 000 000
James „Fluffy” Burton
3
Chłopaki, niczego nie pomylił ... podał tylko przybliżenie, co jest oczywiste, kiedy mówi „w zasadzie”. 2 ^ 10 to ok. 10 ^ 3. W rzeczywistości to przybliżenie jest tak powszechne, że ma nazwę : Mebi , Gibi i Tebi to odpowiednio Mega, Giga i Tera. Jeśli chodzi o brak odpowiedzi na pytanie, @WillManley, masz rację! ;-p
Mike Williamson
9

Ściśle trzymając się pytania, kod Pythona (+ pseudo-kod) to:

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>
Victor Barrantes
źródło
-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 ....
Chikku Jacob
źródło
-1

mamy dwie opcje Obie obejmują importowanie modułu OS

1) import os as funkcja os.stat () zwraca obiekt, który zawiera tak wiele nagłówków, w tym czas utworzenia pliku i czas ostatniej modyfikacji itp. Pośród nich st_size () podaje dokładny rozmiar pliku.

os.stat („nazwa pliku”). st_size ()

2) import os W tym celu musimy podać dokładną ścieżkę do pliku (ścieżkę bezwzględną), a nie ścieżkę względną.

os.path.getsize („ścieżka pliku”)

gunarevuri
źródło