2013-05-31 14 views
7

Nie jestem zupełnie nowy w Pythonie, ale nadal mam problem ze zrozumieniem, co sprawia, że ​​coś "Pythonicznie" (i odwrotnie).Dlaczego nie len (plik) w Pythonie?

Wybacz mi, jeśli to jest głupie pytanie, ale dlaczego nie mogę uzyskać rozmiaru pliku, wykonując len (plik)?

plik. __len__ nie został jeszcze zaimplementowany, więc nie jest potrzebny na coś innego? Czy z jakiegoś powodu byłby mylący/niekonsekwentny, gdyby został zastosowany w celu zwrócenia rozmiaru pliku?

+2

(1) W interaktywny interpreter Pythona wykonać 'import this'. (2) ponieważ aby zaimplementować, musisz przeczytać plik do końca. Więc lepiej spytaj system operacyjny, aby zrobił to za ciebie (np. Jak w [to pytanie SO] (http://stackoverflow.com/questions/6591931/getting-file-size-in-python)) – J0HN

+0

ponieważ ktoś przyszedł z os.stat i statinfo.st_size – varun

Odpowiedz

10

plik jest iteratorem. Aby znaleźć liczbę linii trzeba przeczytać cały plik

sum(1 for line in file) 

jeśli chcesz liczbę bajtów w pliku, użyj os.stat

np

import os 
os.stat(filename).st_size 
+0

OK, iteracja ma sens. Chyba zaimplementuję '__len__' dla pliku, który musiałby odczytać plik do pamięci, a następnie wykonaj len() na buforze. Prawdopodobnie nie jest to świetny pomysł. Możesz zapytać system operacyjny, który już zna rozmiar pliku, stąd os.stat. Dzięki! –

2

I powiedziałbym, ponieważ znalezienie długości zależy od specyficznej dla systemu operacyjnego funkcjonalności. Można znaleźć długość pliku z tym kodem:

import os os.path.getsize('C:\\file.txt')

Można również przeczytać cały plik do sznurka i znaleźć długość łańcucha. Jednak chcesz mieć pewność, że plik nie ma ogromnego rozmiaru, który pochłonie całą twoją pamięć.

2

file zwraca iterator, więc nie można na nim użyć len().

Aby uzyskać rozmiaru pliku można użyć os.stat:

>>> foo = os.stat("abc") 
>>> foo.st_size 
193L 

Jeśli według wielkości na myśli liczbę linii spróbuj tych:

len(open("abc").readlines()) 

lub

sum (1 for _ in open("abc"))

+0

Plik jest iteratorem, tak, ale ma wiele metod. – delnan

+0

'len (open (" abc "). Readlines())' jest bardzo elegancki, dzięki. – PhysicalChemist

+0

Dla uczniów Python 3 "193L" nie oznacza "193 linii", to znaczyło coś w stylu "193 to duża liczba". – Noumenon

14

Pliki mają szerszą definicję, zwłaszcza w Uniksie, niż myślisz. Jaka jest długość drukarki, na przykład? Lub napęd CD-ROM? Oba są plikami w/dev i sortowane w systemie Windows.

Za to, co zwykle uważamy za plik, jaka byłaby jego długość? Wielkość zmiennej? Rozmiar pliku w bajtach? Ta druga ma więcej sensu, ale potem staje się bardziej lodowata. Należy podać rozmiar zawartości pliku lub jego rozmiar na dysku (rozmiar jednostki alokacji modułów). Problem pojawia się ponownie w przypadku plików rzadkich (plików, które mają duże puste sekcje, które nie zajmują miejsca, ale są częścią zwykle raportowanego rozmiaru pliku, obsługiwanego przez niektóre systemy plików, takie jak NTFS i XFS).

Oczywiście, odpowiedź na wszystkie z nich może być: "wybierz jeden i udokumentuj to, co wybrałeś". Być może właśnie to powinno być zrobione, ale żeby być Pythonicznym, coś zwykle musi być jednoznaczne, bez konieczności czytania wielu dokumentów. len(string) jest w większości oczywiste (można zapytać, czy bajty lub znaki są wartością zwracaną), len(array) jest oczywiste, len(file) może nie dość.

+2

To jest dobre sprawdzenie podstawowego problemu, +1 – iruvar

+0

Warto zauważyć, że w Pythonie 3 silna różnica między 'str' (sekwencją punktów kodowych) i' bajtami' (a sekwencja bajtów) w porównaniu do rozróżnienia 'unicode' /' str' w Pythonie 2 sprawia, że ​​jaśniejszy jest sposób definiowania '__len__' dla każdego. – chepner

+0

Dzięki, to jest świetna odpowiedź. Właśnie podałem rozwiązanie @gnibbler, ponieważ był on pierwszym, który zwrócił uwagę na techniczny powód, dla którego '__len__' nie działałby dobrze dla pliku. –

4

Więc wybacz mi, jeśli to głupie pytanie, ale dlaczego nie mogę uzyskać rozmiaru pliku wykonując len (plik)?

Charlesa Burnsa odpowiedź sprawia, że ​​dobry punkt na temat Uniksa za «wszystko jest plikiem» filozofii, i chociaż zawsze można użyć os.fstat() aby uzyskać rozmiar «» dla każdego deskryptora pliku, coś jak ...

import os 

f = open(anything) 
size = os.fstat(f.fileno()).st_size 

... to nie może nic sensownego lub przydatnych powrócić ...

>>> os.fstat(sys.stdout.fileno()).st_size 
0 
>>> fd1, fd2 = os.pipe() 
>>> os.fstat(fd1).st_size 
0 

Myślę, że powodem jest to, że obiekt pliku Python, czy obiekt plikopodobnym, ma reprezentować strumień i strumienie don Z natury mają długość, zwłaszcza jeśli są tylko do zapisu, tak jak sys.stdout.

Zwykle jedyną rzeczą, którą możnagwarancji o plikopodobny obiektu Pythona to, że będzie wspierać co najmniej jeden z read() lub write(), i to wszystko.

1

Prostym sposobem pomiaru liczba znaków będzie:

file = open('file.bin', 'r') 
# Seek to the end. (0 bytes relative to the end) 
file.seek(0, 2) 
length = file.tell() 
Powiązane problemy