Come ottenere la data / ora di creazione e modifica dei file in Python?


934

Ho uno script che deve fare alcune cose in base alla data di creazione e modifica dei file, ma deve essere eseguito su Linux e Windows .

Qual è il miglior modo multipiattaforma per ottenere la creazione e la modifica di file date/timesin Python ?


57
Non è possibile ottenere il tempo di creazione di file in modo multipiattaforma. Vedi docs.python.org/library/os.path.html#os.path.getctime
Glyph

Risposte:


621

Ottenere una sorta di data di modifica in modo multipiattaforma è semplice: basta chiamare e otterrai il timestamp di Unix di quando il file è stato modificato l'ultima volta.os.path.getmtime(path)path

Ottenere le date di creazione dei file , d'altra parte, è complicato e dipende dalla piattaforma, differendo anche tra i tre grandi sistemi operativi:

Mettendo tutto insieme, il codice multipiattaforma dovrebbe assomigliare a questo ...

import os
import platform

def creation_date(path_to_file):
    """
    Try to get the date that a file was created, falling back to when it was
    last modified if that isn't possible.
    See http://stackoverflow.com/a/39501288/1709587 for explanation.
    """
    if platform.system() == 'Windows':
        return os.path.getctime(path_to_file)
    else:
        stat = os.stat(path_to_file)
        try:
            return stat.st_birthtime
        except AttributeError:
            # We're probably on Linux. No easy way to get creation dates here,
            # so we'll settle for when its content was last modified.
            return stat.st_mtime

9
Ho fatto del mio meglio per metterlo insieme (e ho trascorso alcune ore a fare ricerche nel processo), e sono sicuro che sia almeno più corretto delle risposte che erano qui in precedenza, ma questo è un argomento davvero difficile e io ' d apprezzare eventuali correzioni, chiarimenti o altri input che le persone possono offrire. In particolare, vorrei costruire un modo per accedere a questi dati su ext4unità sotto Linux, e mi piacerebbe imparare cosa succede quando Linux legge i file scritti da Windows, o viceversa, dato che usano in modo st_ctimediverso.
Mark Amery,

25
Francamente, il tempo di creazione del file è generalmente abbastanza inutile. Quando si apre un file esistente per scrivere con la modalità "w", non lo sta sostituendo, apre semplicemente il file esistente e lo tronca. Anche se il contenuto del file non è completamente correlato a ciò che aveva durante la creazione, ti verrà comunque detto che il file è stato "creato" ben prima della versione corrente. Al contrario, gli editor che utilizzano Atomic Replace al momento del salvataggio (il file originale è sostituito da un nuovo file temporaneo in corso di elaborazione) mostrerebbero una data di creazione più recente, anche se hai appena eliminato un carattere. Usa il tempo di modifica, non grub per il tempo di creazione.
ShadowRanger,

3
Dopo molti anni, ho finalmente trovato un uso per i tempi di creazione dei file! Sto scrivendo codice per controllare una convenzione di denominazione dei file in alcune directory, quindi prima di tutto voglio considerare i file che sono stati nominati per primi dopo l'istituzione della convenzione. Sostituire l'intero contenuto (mtime) è irrilevante: se era già lì, allora è nonno.
Steve Jessop,

1
Ciao Mark. Propongo una semplificazione. Su Linux, il ritorno stat.st_ctimeè più pertinente perché, in molti casi, il tempo dell'ultima modifica dei metadati può essere il tempo di creazione (almeno ctimeè più vicino al tempo di creazione reale rispetto a mtime). Pertanto, puoi semplicemente sostituire il tuo frammento con stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Cosa ne pensi? Saluti
olibre

4
@olibre "almeno ctime è più vicino al tempo di creazione reale di mtime" - no non lo è; questo è qualcosa che ho visto più volte, ma è totalmente falso. A meno che non hai incasinato manualmente con i valori della tua inode, ctimedovrebbe sempre essere uguale o successiva rispetto mtime, perché un mtimecambiamento provoca un ctimecambiamento (in quanto la mtimestessa è considerata "metadati"). Vedi stackoverflow.com/a/39521489/1709587 dove fornisco alcuni esempi di codice per illustrare questo.
Mark Amery,

676

Hai un paio di scelte. Per uno, è possibile utilizzare le funzioni os.path.getmtimee os.path.getctime:

import os.path, time
print("last modified: %s" % time.ctime(os.path.getmtime(file)))
print("created: %s" % time.ctime(os.path.getctime(file)))

L'altra opzione è utilizzare os.stat:

import os, time
(mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(file)
print("last modified: %s" % time.ctime(mtime))

Nota : ctime()non si riferisce all'ora di creazione sui sistemi * nix, ma piuttosto all'ultima modifica dei dati dell'inode. (grazie a Kojiro per aver reso più chiaro questo fatto nei commenti fornendo un link a un post sul blog interessante)


169
Nel caso in cui qualcuno manchi il commento di @ Glyph alla domanda, ctime non significa tempo di creazione su sistemi POSIX . Mi chiedo quante persone hanno scremato questo post negli ultimi tre anni e hanno continuato a scrivere codice buggy.
Kojiro,

16
Tieni presente che il primo esempio ti fornisce una stringa, non un datetime o un numero.
gak,

1
@kojiro il post sul blog che hai collegato potrebbe essere più esplicito che su Unix un file ctimeviene aggiornato ogni volta che lo mtimefa (dato che si mtimetratta di "metadati"), e quindi ctimenormalmente è sempre uguale o precedente al mtime. Trattare ctimecome tempo "creato" quindi non ha alcun senso. -1!
Mark Amery,

La tua prima opzione restituisce gli stessi risultati sia per la creazione del file che per l'ultima modifica! Last modified: Fri Jan 31 11:08:13 2020e Created: Fri Jan 31 11:08:13 2020su Linux Ubuntu 16.04!
Färid Alijani,

Scopro che time.ctime(os.path.getmtime(file))restituisce 2 tipi di stringhe, a seconda che il file sia stato modificato dal sistema o dall'utente. Se è stata modificata dal sistema, la stringa avrà 2 spazi tra il mese e il giorno. Non so perché
Matteo Antolini il

376

La migliore funzione da utilizzare per questo è os.path.getmtime () . Internamente, questo usa e basta os.stat(filename).st_mtime.

Il modulo datetime è il timestamp migliore per manipolare, quindi puoi ottenere la data di modifica come un datetimeoggetto come questo:

import os
import datetime
def modification_date(filename):
    t = os.path.getmtime(filename)
    return datetime.datetime.fromtimestamp(t)

Esempio di utilizzo:

>>> d = modification_date('/var/log/syslog')
>>> print d
2009-10-06 10:50:01
>>> print repr(d)
datetime.datetime(2009, 10, 6, 10, 50, 1)

1
Anche questa risposta è un po 'sbagliata. getmtimeè la cosa più vicina disponibile su Unix (dove non è possibile ottenere le date di creazione), ma sicuramente non è la migliore funzione da usare su Windows, dove ctimeè l'ora della creazione.
Mark Amery,

3
@MarkAmery: questa risposta è chiaramente etichettata come relativa al tempo di modifica.
ArtOfWarfare il

47

os.stat https://docs.python.org/2/library/stat.html#module-stat

modifica: nel codice più recente dovresti probabilmente usare os.path.getmtime () (grazie a Christian Oudard)
ma nota che restituisce un valore in virgola mobile di time_t con frazione di secondi (se il tuo sistema operativo lo supporta)


44
os.path.getmtime () è fatto per questo, e più semplice.
Christian Oudard,

5
La clausola "nel codice più recente" qui è un po 'fuorviante. os.path.getmtime()è in circolazione da Python 1.5.2 (vedi i vecchi documenti ), rilasciato prima che avessi perso la maggior parte dei miei denti da latte e quasi un decennio prima che tu scrivessi la versione originale di questa risposta.
Mark Amery,

39

Esistono due metodi per ottenere il mod time, os.path.getmtime () o os.stat (), ma il ctime non è affidabile multipiattaforma (vedi sotto).

os.path.getmtime ()

getmtime ( percorso )
Restituisce l'ora dell'ultima modifica del percorso. Il valore restituito è un numero che indica il numero di secondi dall'epoca (vedere il modulo temporale). Sollevare os.error se il file non esiste o è inaccessibile. Novità nella versione 1.5.2. Modificato nella versione 2.3: Se os.stat_float_times () restituisce True, il risultato è un numero in virgola mobile.

os.stat ()

stat ( percorso )
Esegue una chiamata di sistema stat () sul percorso indicato. Il valore restituito è un oggetto i cui attributi corrispondono ai membri della struttura stat, vale a dire: st_mode (bit di protezione), st_ino (numero di inode), st_dev (dispositivo), st_nlink (numero di hard link), st_uid (ID utente del proprietario ), st_gid (ID gruppo del proprietario), st_size (dimensione del file, in byte), st_atime (ora dell'accesso più recente), st_mtime (ora dell'ultima modifica del contenuto), st_ctime (dipendente dalla piattaforma; ora dell'ultima modifica dei metadati su Unix o l'ora della creazione su Windows) :

>>> import os
>>> statinfo = os.stat('somefile.txt')
>>> statinfo
(33188, 422511L, 769L, 1, 1032, 100, 926L, 1105022698,1105022732, 1105022732)
>>> statinfo.st_size
926L
>>> 

Nell'esempio sopra useresti statinfo.st_mtime o statinfo.st_ctime per ottenere rispettivamente mtime e ctime.


13

In Python 3.4 e versioni successive, è possibile utilizzare l' interfaccia del modulo pathlib orientata agli oggetti che include wrapper per gran parte del modulo os. Ecco un esempio di come ottenere le statistiche del file.

>>> import pathlib
>>> fname = pathlib.Path('test.py')
>>> assert fname.exists(), f'No such file: {fname}'  # check that the file exists
>>> print(fname.stat())
os.stat_result(st_mode=33206, st_ino=5066549581564298, st_dev=573948050, st_nlink=1, st_uid=0, st_gid=0, st_size=413, st_atime=1523480272, st_mtime=1539787740, st_ctime=1523480272)

Per ulteriori informazioni su ciò che os.stat_resultcontiene, consultare la documentazione . Per il tempo di modifica desiderato fname.stat().st_mtime:

>>> import datetime
>>> mtime = datetime.datetime.fromtimestamp(fname.stat().st_mtime)
>>> print(mtime)
datetime.datetime(2018, 10, 17, 10, 49, 0, 249980)

Se si desidera il tempo di creazione su Windows o la modifica dei metadati più recente su Unix, si utilizzerà fname.stat().st_ctime:

>>> ctime = datetime.datetime.fromtimestamp(fname.stat().st_ctime)
>>> print(ctime)
datetime.datetime(2018, 4, 11, 16, 57, 52, 151953)

Questo articolo contiene informazioni più utili ed esempi per il modulo pathlib.


11

os.statrestituisce una tupla con nome st_mtimee st_ctimeattributi. Il tempo di modifica è st_mtimesu entrambe le piattaforme; sfortunatamente, su Windows, ctimesignifica "tempo di creazione", mentre su POSIX significa "tempo di cambio". Non sono a conoscenza di alcun modo per ottenere il tempo di creazione su piattaforme POSIX.


Ecco di più sulle tuple con tag: stackoverflow.com/questions/2970608/… Funzionano come le tuple, ma provane dir(..)una. Ad esempiodir(os.stat(os.listdir('.')[0]))
Evgeni Sergeev il

9
import os, time, datetime

file = "somefile.txt"
print(file)

print("Modified")
print(os.stat(file)[-2])
print(os.stat(file).st_mtime)
print(os.path.getmtime(file))

print()

print("Created")
print(os.stat(file)[-1])
print(os.stat(file).st_ctime)
print(os.path.getctime(file))

print()

modified = os.path.getmtime(file)
print("Date modified: "+time.ctime(modified))
print("Date modified:",datetime.datetime.fromtimestamp(modified))
year,month,day,hour,minute,second=time.localtime(modified)[:-3]
print("Date modified: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))

print()

created = os.path.getctime(file)
print("Date created: "+time.ctime(created))
print("Date created:",datetime.datetime.fromtimestamp(created))
year,month,day,hour,minute,second=time.localtime(created)[:-3]
print("Date created: %02d/%02d/%d %02d:%02d:%02d"%(day,month,year,hour,minute,second))

stampe

somefile.txt
Modified
1429613446
1429613446.0
1429613446.0

Created
1517491049
1517491049.28306
1517491049.28306

Date modified: Tue Apr 21 11:50:46 2015
Date modified: 2015-04-21 11:50:46
Date modified: 21/04/2015 11:50:46

Date created: Thu Feb  1 13:17:29 2018
Date created: 2018-02-01 13:17:29.283060
Date created: 01/02/2018 13:17:29

-1: Come le altre risposte, questo non ti darà il tempo di creazione del file su Windows (che, ancora una volta, non è nemmeno menzionato nella risposta).
ntninja,

@ntninja ne sei sicuro? io uso solo Windows e questo funziona assolutamente. ho scritto questo copione all'inizio del 2015. Trovo che fosse più chiaro, diretto al punto, completo e autoesplicativo di altri qui. (che mi è capitato di decidere di cercare qui invece dei miei vecchi script in caso ci fosse qualcosa di nuovo. No ... questo è il modo)
Pozza

Oh, intendevo dire "... questo non ti darà il tempo di creazione del file, a meno che tu non sia su Windows". Scusate! Resta il fatto che questa risposta non è portatile e non menziona questo fatto. (Esempio di output su Linux: pastebin.com/50r5vGBE )
ntninja

@ntninja allora andrai a dirlo a tutti gli altri?
Pozza

Ho già lasciato alcuni altri commenti qui e posterò presto una risposta che funziona su (recente) Linux. Ma davvero, l'unica cosa sbagliata nel tuo post è che è la sola risposta di Windows che non menziona questo fatto. Nella domanda OP ha anche chiesto specificamente una soluzione compatibile con Windows e Linux. In quanto tale, penso che sarebbe molto utile se tu aggiungessi questo "dettaglio" da qualche parte in alto, in modo che le persone non inducano in errore a pensare che il tempo è quello che stanno cercando quando prendono di mira più piattaforme.
ntninja,

2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 

-1: Come menzionato altrove, questo non ti darà il tempo di creazione del file, a meno che tu non sia su Windows (che la risposta non menziona nemmeno!).
ntninja

0

Se i seguenti collegamenti simbolici non sono importanti, è possibile utilizzare anche il os.lstatcomando incorporato.

>>> os.lstat("2048.py")
posix.stat_result(st_mode=33188, st_ino=4172202, st_dev=16777218L, st_nlink=1, st_uid=501, st_gid=20, st_size=2078, st_atime=1423378041, st_mtime=1423377552, st_ctime=1423377553)
>>> os.lstat("2048.py").st_atime
1423378041.0

Questo darà il tempo dell'ultima lettura (almeno su Unix), che sicuramente non è quello che è stato chiesto.
Mark Amery,

0

Potrebbe valere la pena dare un'occhiata alla crtimelibreria che implementa l'accesso multipiattaforma al tempo di creazione del file.

from crtime import get_crtimes_in_dir

for fname, date in get_crtimes_in_dir(".", raise_on_error=True, as_epoch=False):
    print(fname, date)
    # file_a.py Mon Mar 18 20:51:18 CET 2019

1
Lo sconsiglio vivamente: utilizza debugfssu Linux che è per definizione instabile, richiede l'accesso root di livello superiore per tutto e praticamente ogni aspetto tende a essere una delle cose di cui tua madre ti ha sempre messo in guardia. (Ma sì, probabilmente funziona se sei davvero disperato e capita di essere il vero superutente su un sistema senza avvio sicuro ...)
ntninja

@ntninja Probabilmente non userei mai neanche in produzione, ma potrebbe essere utile per "home scripting".
Delgan

-2

os.statinclude il tempo di creazione. Non esiste una definizione di st_anything per l'elemento os.stat()che contiene il tempo.

Quindi prova questo:

os.stat('feedparser.py')[8]

Confrontalo con la tua data di creazione nel file in ls -lah

Dovrebbero essere uguali.


6
Sbagliato! os.stat ('feedparser.py') [8] si riferisce a st_mtime, non al tempo di creazione. Fare riferimento alla documentazione: docs.python.org/library/os.html#os.stat
millerdev,

4
Si prega di utilizzare .st_ctime invece di numeri brutti [8].
Guettli,

-3

Sono stato in grado di ottenere il tempo di creazione su posix eseguendo il comando stat del sistema e analizzando l'output.

commands.getoutput('stat FILENAME').split('\"')[7]

In esecuzione stat al di fuori di Python dal Terminale (OS X) restituito:

805306374 3382786932 -rwx------ 1 km staff 0 1098083 "Aug 29 12:02:05 2013" "Aug 29 12:02:05 2013" "Aug 29 12:02:20 2013" "Aug 27 12:35:28 2013" 61440 2150 0 testfile.txt

... dove il quarto datetime è la creazione del file (piuttosto che il tempo di cambio ctime come altri commenti hanno notato).


13
-1: Analisi un'uscita significato per gli esseri umani da un comando shell è molto cattiva idea. E questo comando non è nemmeno cross-compatibile.
MestreLion,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.