2013-05-31 11 views
7

Non sono esattamente nuovo di Python, ma ho ancora difficoltà a capire cosa rende qualcosa "Pythonic" (e il contrario).Perché no len (file) in Python?

Quindi, perdonami se questa è una domanda stupida, ma perché non riesco a ottenere la dimensione di un file facendo un len (file)?

file. __len__ non è nemmeno implementato, quindi non è come se fosse necessario per qualcos'altro? Sarebbe confuso/incoerente per qualche motivo se fosse implementato per restituire la dimensione del file?

+2

(1) In Python interprete interattivo eseguire 'importazione this'. (2) perché per implementare questo è necessario leggere il file fino alla fine. Quindi, è meglio chiedere a OS di farlo per te (ad esempio, come in [questa domanda SO] (http://stackoverflow.com/questions/6591931/getting-file-size-in-python)) – J0HN

+0

perché qualcuno è venuto con os.stat e statinfo.st_size – varun

risposta

10

file è un iteratore. Per trovare il numero di linee è necessario leggere l'intero file

sum(1 for line in file) 

se si desidera che il numero di byte in un file, utilizzare os.stat

esempio

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

OK, la cosa iteratore ha senso. Immagino di implementare '__len__' per un file che dovrebbe leggere il file in memoria e quindi fare un len() sul buffer. Probabilmente non è una grande idea. Quindi puoi chiedere al sistema operativo, che conosce già la dimensione del file, quindi os.stat. Grazie! –

2

I direbbe perché la ricerca della lunghezza dipende dalla funzionalità specifica del sistema operativo. È possibile trovare la lunghezza di un file con questo codice:

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

Si potrebbe anche leggere l'intero file in una stringa e trovare la lunghezza della stringa. Tuttavia, si vorrebbe essere sicuri che il file non sia di dimensioni enormi che possa consumare tutta la memoria.

2

file restituisce un iteratore, quindi non è possibile utilizzare len() su di esso.

Per ottenere la dimensione di un file, è possibile utilizzare os.stat:

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

Se per dimensione si intende il numero di linea quindi provare questi:

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

o

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

+0

Un file è un iteratore, sì, ma ha molti metodi. – delnan

+0

'len (aperto (" abc "). Readlines())' è molto elegante, grazie. – PhysicalChemist

+0

Per gli studenti di Python 3, "193L" non significa "193 righe", significava qualcosa come "193 è un numero grande". – Noumenon

14

I file hanno una definizione più ampia, in particolare in Unix, di quanto tu stia pensando. Qual è la lunghezza di una stampante, ad esempio? O un'unità CD-ROM? Entrambi sono file in/dev e in Windows.

Per quello che normalmente pensiamo come un file, quale sarebbe la sua lunghezza? La dimensione della variabile? La dimensione del file in byte? Quest'ultimo ha più senso, ma poi diventa più ickier. Dovrebbe essere elencata la dimensione del contenuto del file, o la sua dimensione su disco (dimensione dell'unità di allocazione del modulo). La domanda sorge di nuovo per file sparsi (file che hanno sezioni vuote di grandi dimensioni che non occupano spazio, ma fanno parte delle dimensioni normalmente riportate del file, supportate da alcuni file system come NTFS e XFS).

Ovviamente, la risposta a tutti questi potrebbe essere, "basta sceglierne uno e documentare ciò che hai scelto". Forse questo è esattamente ciò che dovrebbe essere fatto, ma per essere Pythonic, qualcosa di solito deve essere chiaro senza dover leggere un sacco di documenti. len(string) è quasi ovvio (si potrebbe chiedere se i byte oi caratteri sono il valore restituito), len(array) è ovvio, len(file) forse non abbastanza.

+2

Questo è un buon esame del problema principale, +1 – iruvar

+0

Vale la pena notare che in Python 3, la forte distinzione tra 'str' (una sequenza di punti di codice) e' byte' (a sequenza di byte) rispetto alla distinzione 'unicode' /' str' in Python 2 rende più chiaro come '__len__' debba essere definito per ciascuno. – chepner

+0

Grazie, questa è un'ottima risposta. Ho appena dato la soluzione a @gnibbler perché è stato il primo a sottolineare la ragione tecnica per cui '__len__' non avrebbe funzionato bene per un file. –

4

quindi perdonatemi se questa è una domanda stupida, ma perché non posso ottenere la dimensione di un file facendo una len (file)?

Charles Burns' risposta rende un buon punto di 'ogni cosa è un file' di Unix filosofia, e, anche se è sempre possibile utilizzare os.fstat() per ottenere la 'dimensione' per qualsiasi descrittore di file, con qualcosa di simile ...

import os 

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

... non può restituire qualcosa di significativo o utili ...

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

Penso che il motivo è che un oggetto file Python, o un oggetto simile a file, dovrebbe rappresentare un flusso e i flussi don Hanno intrinsecamente una lunghezza, specialmente se sono di sola scrittura, come sys.stdout.

Di solito, l'unica cosa che si può garanzia di un oggetto simile a file Python è che sosterrà almeno una delle read() o write(), e che su di esso.

1

Un modo semplice per misurare il numero di caratteri potrebbe essere:

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