C'è un file che vorrei essere sicuro che non cresca più di 2 GB (dato che deve essere eseguito su un sistema che usa ext 2). Qual è un buon modo per controllare le dimensioni di un file tenendo presente che scriverò su questo file tra un controllo e l'altro? In particolare, devo preoccuparmi delle modifiche bufferizzate e non aggiornate che non sono ancora state scritte sul disco?Come determinare la dimensione di un file aperto in Python?
risposta
Si potrebbe iniziare con qualcosa di simile:
class TrackedFile(file):
def __init__(self, filename, mode):
self.size = 0
super(TrackedFile, self).__init__(filename, mode)
def write(self, s):
self.size += len(s)
super(TrackedFile, self).write(s)
allora si potrebbe utilizzare in questo modo:
>>> f = TrackedFile('palindrome.txt', 'w')
>>> f.size
0
>>> f.write('A man a plan a canal ')
>>> f.size
21
>>> f.write('Panama')
27
Ovviamente, questa implementazione non funziona se non si sta scrivendo il file da zero, ma è possibile adattare il metodo __init__
per gestire i dati iniziali. Potrebbe anche essere necessario sovrascrivere altri metodi: writelines
, ad esempio.
Questo funziona indipendentemente dalla codifica, poiché le stringhe sono solo sequenze di byte.
>>> f2 = TrackedFile('palindrome-latin1.txt', 'w')
>>> f2.write(u'A man a plan a canál '.encode('latin1')
>>> f3 = TrackedFile('palindrome-utf8.txt', 'w')
>>> f3.write(u'A man a plan a canál '.encode('utf-8'))
>>> f2.size
21
>>> f3.size
22
+1: questa è un'idea davvero intelligente. Mi piace! – jathanism
Questo non è in realtà. Si usano ASCII, ISO1559 e UTF-8, il risultato sarà lo stesso, ma la dimensione del disco non sarà. –
No. Funziona anche per altre codifiche, se si usano stringhe reali. Risposta modificata per dimostrare. – jcdyer
Forse non quello che vuoi, ma lo suggerirò comunque.
import os
a = os.path.getsize("C:/TestFolder/Input/1.avi")
In alternativa, per un file aperto è possibile utilizzare la funzione di fstat, che può essere utilizzato su un file aperto. Ci vuole un handle di file intero, non un oggetto file, quindi bisogna utilizzare il metodo fileno sul oggetto file:
a = open("C:/TestFolder/Input/1.avi")
b = os.fstat(a.fileno()).st_size
più affidabili sarebbe creare una classe di avvolgimento che controllare le dimensioni del file quando lo si apre, traccia le operazioni di scrittura e ricerca, conta le dimensioni correnti in base a tali operazioni e previene il superamento del limite di dimensioni.
Oppure, se il file è già aperto:
>>> fsock = open('/etc/hosts', 'rb').read()
>>> len(fsock)
444
Ecco quanti byte del file è.
os.fstat(file_obj.fileno()).st_size
dovrebbe fare il trucco. Penso che restituirà i byte scritti. Puoi sempre fare un flush in anticipo se sei preoccupato del buffering.
E funziona anche in modalità append! Grazie. E sì, arrossirei prima di chiamare questo. –
Non ho dimestichezza con python, ma l'oggetto stream (o quello che si ottiene quando si apre un file) non ha una proprietà che contiene la posizione corrente del flusso?
Simile a quello che si ottiene con la funzione ftell() C o Stream.Position in .NET.
Ovviamente, questo funziona solo se si è posizionati alla fine dello stream, che si è se si sta attualmente scrivendo su di esso.
Il vantaggio di questo approccio è che non è necessario chiudere il file o preoccuparsi di dati non aggiornati.
'filehandle.tell()' mostra infatti il numero di byte nel file aperto e funziona in modalità di scrittura o di aggiunta. Non sono sicuro del motivo per cui tutte queste risposte più complesse sono state svalutate. – hurfdurf
@hurfdurf No, 'f.tell()' non sembra funzionare in modo affidabile in modalità append. A meno che tu non abbia prima 'f.seek (0,2)'. Non ho idea del perché. –
Anche se questa è una vecchia domanda, penso che Isak abbia la soluzione più semplice. Ecco come farlo in Python:
# Assuming f is an open file
>>> pos = f.tell() # Save the current position
>>> f.seek(0, 2) # Seek to the end of the file
>>> length = f.tell() # The current position is the length
>>> f.seek(pos) # Return to the saved position
>>> print length
1024
Penso che nella prima riga (salva la posizione corrente), dovresti usare f.tell(), non il seek(), che causerebbe un'eccezione dato che seek() ha bisogno di almeno 1 argomento. – Jkm
@Jkm Sì, hai ragione! Non sono sicuro di quanto mi sia mancato. Grazie! – Trenton
Questo calcola correttamente la dimensione del file, ma non ripristinerà la posizione correttamente a causa di problemi noti con [modalità di aggiunta in append] (https://stackoverflow.com/questions/31680677/). –
C'è un motivo non si può semplicemente tenere traccia della dimensione del file da soli - cioè, vedere ciò che la dimensione è quando lo si apre e incrementare un contatore quando si scrive ?Non particolarmente elegante, ma dovrebbe funzionare. –
Suppongo che sia una possibilità a cui non avevo pensato ... Potrei provare anche quello. –
Tuttavia non è inefficiente? –