Wie erhalte ich das Datum und die Uhrzeit der Dateierstellung und -änderung in Python?

932

Ich habe ein Skript, das einige Dinge basierend auf den Erstellungs- und Änderungsdaten von Dateien ausführen muss, aber unter Linux und Windows ausgeführt werden muss .

Was ist der beste plattformübergreifende Weg, um Dateien date/timesin Python zu erstellen und zu ändern ?

Mark Biek
quelle
57
Sie können die Zeit für die Dateierstellung nicht plattformübergreifend abrufen. Siehe docs.python.org/library/os.path.html#os.path.getctime
Glyph

Antworten:

620

Es ist einfach, plattformübergreifend ein Änderungsdatum zu erhalten. Rufen Sie einfach an und Sie erhalten den Unix-Zeitstempel, wann die Datei zuletzt geändert wurde.os.path.getmtime(path)path

Erste Datei Erstellung Daten, auf der anderen Seite, ist knifflig und plattformabhängig und unterscheiden sich auch zwischen den drei großen OSes:

Zusammen sollte plattformübergreifender Code ungefähr so ​​aussehen ...

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
Mark Amery
quelle
9
Ich habe mein Bestes getan, um dies zusammenzubringen (und ein paar Stunden damit verbracht, nachzuforschen), und ich bin sicher, dass es zumindest korrekter ist als die Antworten, die hier zuvor waren, aber das ist ein wirklich schwieriges Thema, und ich ' Ich würde mich über Korrekturen, Klarstellungen oder andere Eingaben freuen, die Menschen anbieten können. Insbesondere möchte ich eine Methode für den Zugriff auf diese Daten auf ext4Laufwerken unter Linux entwickeln und erfahren, was passiert, wenn Linux von Windows geschriebene Dateien liest oder umgekehrt, da sie st_ctimeunterschiedlich verwendet werden.
Mark Amery
25
Ehrlich gesagt ist die Zeit für die Dateierstellung normalerweise ziemlich nutzlos. Wenn Sie eine vorhandene Datei zum Schreiben im Modus öffnen "w", wird sie nicht ersetzt, sondern nur die vorhandene Datei geöffnet und abgeschnitten. Auch wenn der Dateiinhalt in keinerlei Beziehung zu dem steht, was er bei der Erstellung hatte, wird Ihnen dennoch mitgeteilt, dass die Datei lange vor der aktuellen Version "erstellt" wurde. Umgekehrt würden Editoren, die beim Speichern atomares Ersetzen verwenden (die Originaldatei wird durch eine neue temporäre Datei ersetzt), ein neueres Erstellungsdatum anzeigen, selbst wenn Sie nur ein Zeichen gelöscht haben. Verwenden Sie die Änderungszeit, und suchen Sie nicht nach der Erstellungszeit.
ShadowRanger
3
Nach vielen Jahren habe ich endlich eine Verwendung für die Dateierstellungszeit gefunden! Ich schreibe Code, um eine Dateinamenskonvention in bestimmten Verzeichnissen zu überprüfen. Daher möchte ich zunächst Dateien berücksichtigen, die zuerst nach der Einführung der Konvention benannt wurden. Das Ersetzen des gesamten Inhalts (mtime) ist irrelevant: Wenn es bereits vorhanden war, ist es großväterlich.
Steve Jessop
1
Hallo Mark. Ich schlage eine Vereinfachung vor. Unter Linux ist die Rückgabe stat.st_ctimerelevanter, da in vielen Fällen der Zeitpunkt der letzten Metadatenänderung die Erstellungszeit sein kann (zumindest ctimenäher an der tatsächlichen Erstellungszeit als mtime). Daher können Sie Ihr Snippet einfach durch ersetzen stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Was denken Sie? Cheers
Olibre
4
@olibre "mindestens ctime ist näher an der tatsächlichen Erstellungszeit als mtime" - nein, ist es nicht; Das habe ich schon mehrmals gesehen, aber es ist völlig falsch. Es sei denn , Sie manuell mit den Werten in Ihrer inode messed haben, ctimesollte immer gleich oder später als mtime, weil eine mtimeÄnderung bewirkt eine ctimeÄnderung (weil die für mtimesich betrachtet wird „Metadaten“). Siehe stackoverflow.com/a/39521489/1709587, wo ich einen Beispielcode zur Veranschaulichung bereitstelle.
Mark Amery
676

Sie haben ein paar Möglichkeiten. Zum einen können Sie die Funktionen os.path.getmtimeund os.path.getctimeverwenden:

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

Ihre andere Option ist 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))

Hinweis : ctime()Bezieht sich nicht auf die Erstellungszeit auf * nix-Systemen, sondern auf das letzte Mal, als sich die Inode-Daten geändert haben. (Danke an kojiro, dass er diese Tatsache in den Kommentaren durch einen Link zu einem interessanten Blog-Beitrag klarer gemacht hat)

Bryan Oakley
quelle
169
Nur für den Fall, dass jemand den Kommentar von @ Glyph zu dieser Frage verpasst, bedeutet ctime nicht die Erstellungszeit auf POSIX-Systemen . Ich frage mich, wie viele Leute diesen Beitrag in den letzten drei Jahren überflogen und anschließend Buggy-Code geschrieben haben.
Kojiro
16
Denken Sie daran, dass das erste Beispiel eine Zeichenfolge enthält, keine Datums- / Uhrzeitangabe oder Zahl.
Gak
1
@kojiro Der Blog-Beitrag, auf den Sie verlinkt haben, könnte expliziter sein, dass unter Unix eine Datei immer ctimedann aktualisiert wird, wenn dies der mtimeFall ist (da dies mtime"Metadaten" sind), und daher ctimeist der normalerweise immer gleich oder vor dem mtime. Die Behandlung ctimeals „geschaffen“ Zeit also keinen Sinn macht. -1!
Mark Amery
Ihre erste Option liefert die gleichen Ergebnisse sowohl für die Dateierstellung als auch für die letzte Änderung! Last modified: Fri Jan 31 11:08:13 2020und Created: Fri Jan 31 11:08:13 2020unter Linux Ubuntu 16.04!
Färid Alijani
Ich stelle fest, dass time.ctime(os.path.getmtime(file))zwei Arten von Zeichenfolgen zurückgegeben werden, je nachdem, ob die Datei vom System oder vom Benutzer geändert wurde. Wenn es vom System geändert wurde, hat die Zeichenfolge zwischen dem Monat und dem Tag zwei Leerzeichen. Ich weiß nicht warum
Matteo Antolini
376

Die beste Funktion hierfür ist os.path.getmtime () . Intern wird dies nur verwendet os.stat(filename).st_mtime.

Das Datum / Uhrzeit-Modul ist die beste Zeitleiste zum Bearbeiten, sodass Sie das Änderungsdatum als datetimeObjekt wie folgt abrufen können :

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

Anwendungsbeispiel:

>>> 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)
Christian Oudard
quelle
1
Diese Antwort ist auch ein bisschen falsch. getmtimeist die nächste unter Unix verfügbare Funktion (bei der das Abrufen von Erstellungsdaten nicht möglich ist), aber definitiv nicht die beste Funktion für Windows, bei der ctimees sich um eine Erstellungszeit handelt.
Mark Amery
3
@MarkAmery - Bei dieser Antwort handelt es sich eindeutig um eine Änderungszeit.
ArtOfWarfare
47

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

edit: In neuerem Code sollten Sie wahrscheinlich os.path.getmtime () verwenden (danke Christian Oudard),
aber beachten Sie, dass es einen Gleitkommawert von time_t mit Bruchteilen von Sekunden zurückgibt (wenn Ihr Betriebssystem dies unterstützt).

Martin Beckett
quelle
44
os.path.getmtime () ist dafür gemacht und einfacher.
Christian Oudard
5
Die Klausel "in neuerem Code" hier ist etwas irreführend. os.path.getmtime()gibt es seit Python 1.5.2 (siehe die alten Dokumente ), das veröffentlicht wurde, bevor ich die meisten meiner Milchzähne verloren hatte und fast ein Jahrzehnt, bevor Sie die Originalversion dieser Antwort geschrieben haben.
Mark Amery
39

Es gibt zwei Methoden, um die Mod-Zeit abzurufen: os.path.getmtime () oder os.stat (), aber die ctime ist nicht zuverlässig plattformübergreifend (siehe unten).

os.path.getmtime ()

getmtime ( Pfad ) Gibt
die Zeit der letzten Änderung des Pfads zurück. Der Rückgabewert ist eine Zahl, die die Anzahl der Sekunden seit der Epoche angibt (siehe Zeitmodul). Erhöhen Sie os.error, wenn die Datei nicht vorhanden ist oder nicht zugänglich ist. Neu in Version 1.5.2. In Version 2.3 geändert: Wenn os.stat_float_times () True zurückgibt, ist das Ergebnis eine Gleitkommazahl.

os.stat ()

stat ( Pfad )
Führen Sie einen stat () - Systemaufruf für den angegebenen Pfad aus. Der Rückgabewert ist ein Objekt, dessen Attribute den Mitgliedern der stat-Struktur entsprechen, nämlich: st_mode (Schutzbits), st_ino (Inode-Nummer), st_dev (Gerät), st_nlink (Anzahl der festen Links), st_uid (Benutzer-ID des Eigentümers) ), st_gid (Gruppen-ID des Eigentümers), st_size (Dateigröße in Byte), st_atime (Zeitpunkt des letzten Zugriffs), st_mtime (Zeitpunkt der letzten Inhaltsänderung ), st_ctime (plattformabhängig; Zeitpunkt der letzten Metadatenänderung) unter Unix oder zum Zeitpunkt der Erstellung unter Windows) :

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

Im obigen Beispiel würden Sie statinfo.st_mtime oder statinfo.st_ctime verwenden, um die mtime bzw. ctime abzurufen.

Jay
quelle
13

In Python 3.4 und höher können Sie die objektorientierte Pathlib-Modulschnittstelle verwenden, die Wrapper für einen Großteil des OS-Moduls enthält. Hier ist ein Beispiel für das Abrufen der Dateistatistiken.

>>> 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)

Weitere Informationen zu den Inhaltsstoffen os.stat_resultfinden Sie in der Dokumentation . Für die gewünschte Änderungszeit 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)

Wenn Sie die Erstellungszeit unter Windows oder die letzte Änderung der Metadaten unter Unix wünschen, würden Sie Folgendes verwenden fname.stat().st_ctime:

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

Dieser Artikel enthält weitere hilfreiche Informationen und Beispiele für das Pathlib-Modul.

Steven C. Howell
quelle
11

os.statGibt ein benanntes Tupel mit st_mtimeund st_ctimeAttributen zurück. Die Änderungszeit ist st_mtimeauf beiden Plattformen; Leider ctimebedeutet unter Windows "Erstellungszeit", während es unter POSIX "Änderungszeit" bedeutet. Mir ist keine Möglichkeit bekannt, die Erstellungszeit auf POSIX-Plattformen zu ermitteln.

Mithrandi
quelle
Hier erfahren Sie mehr über getaggte Tupel: stackoverflow.com/questions/2970608/… Sie funktionieren wie Tupel, aber probieren Sie dir(..)eines an. ZBdir(os.stat(os.listdir('.')[0]))
Evgeni Sergeev
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))

druckt

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
Pfütze
quelle
-1: Wie bei anderen Antworten wird die Erstellungszeit der Datei unter Windows nicht angegeben (was in der Antwort wiederum nicht einmal erwähnt wird).
8.
@ntninja bist du dir da sicher? Ich benutze nur Windows und das funktioniert absolut. Ich habe dieses Skript Anfang 2015 geschrieben. Ich finde es klarer, auf den Punkt gebracht, vollständig und selbsterklärend als andere hier. (was ich zufällig beschlossen habe, hier statt meiner alten Skripte nachzuschlagen, nur für den Fall, dass es etwas Neues gibt. Nein ... das ist der Weg)
Puddle
Oh, ich wollte damit sagen: "... dies gibt Ihnen keine Zeit für die Erstellung der Datei, es sei denn, Sie arbeiten unter Windows." Es tut uns leid! Tatsache bleibt, dass diese Antwort nicht portabel ist und diese Tatsache nicht erwähnt. (Beispielausgabe unter Linux: pastebin.com/50r5vGBE )
ntninja
@ntninja willst du es dann allen anderen erzählen?
Pfütze
Ich habe hier bereits einige andere Kommentare hinterlassen und werde bald eine Antwort veröffentlichen, die auch unter (neuem) Linux funktioniert. Aber wirklich, das einzige, was in Ihrem Beitrag falsch ist, ist, dass es nur eine Windows-Antwort ist, die diese Tatsache nicht erwähnt. In der Frage OP wurde sogar speziell nach einer Windows- und Linux-kompatiblen Lösung gefragt. Daher denke ich, dass es sehr hilfreich wäre, wenn Sie dieses „Detail“ irgendwo oben hinzufügen würden, damit die Leute nicht irreführen, wenn sie denken, dass ctime das ist, wonach sie suchen, wenn sie auf mehrere Plattformen abzielen.
ntninja
2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 
unmontiert
quelle
-1: Wie an anderer Stelle erwähnt, erhalten Sie keine Erstellungszeit für die Datei, es sei denn, Sie arbeiten unter Windows (was in der Antwort nicht einmal erwähnt wird!).
ntninja
0

Wenn das os.lstatBefolgen symbolischer Links nicht wichtig ist, können Sie auch die integrierte Funktion verwenden.

>>> 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
Low Kian Seong
quelle
Dies gibt die Zeit des letzten Lesens an (zumindest unter Unix), was definitiv nicht das ist, wonach gefragt wurde.
Mark Amery
0

Es kann sich lohnen, einen Blick auf die crtimeBibliothek zu werfen, die den plattformübergreifenden Zugriff auf die Dateierstellungszeit implementiert.

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
Delgan
quelle
1
Ich rate dringend davon ab: Es wird debugfsunter Linux verwendet, das per Definition instabil ist, für alles Root-Zugriff auf oberster Ebene erfordert und in so ziemlich jedem Aspekt eines der Dinge ist, vor denen deine Mutter dich immer gewarnt hat. (Aber ja, es funktioniert wahrscheinlich, wenn Sie wirklich verzweifelt sind und zufällig der echte Superuser auf einem System ohne sicheren Start sind…)
ntninja
@ntninja würde ich wahrscheinlich auch nie in der Produktion verwenden, aber es kann für "Home Scripting" nützlich sein.
Delgan
-2

os.statenthält die Erstellungszeit. Es gibt einfach keine Definition von st_anything für das Element os.stat(), das die Zeit enthält.

Versuchen Sie Folgendes:

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

Vergleichen Sie das mit Ihrem Erstellungsdatum in der Datei in ls-lah

Sie sollten gleich sein.

Stange
quelle
6
Falsch! os.stat ('feedparser.py') [8] bezieht sich auf st_mtime, nicht auf die Erstellungszeit. Bitte beziehen Sie sich auf die Dokumentation: docs.python.org/library/os.html#os.stat
millerdev
4
Bitte verwenden Sie .st_ctime anstelle von hässlichen Zahlen [8].
Guettli
-3

Ich konnte die Erstellungszeit für posix ermitteln, indem ich den Befehl stat des Systems ausführte und die Ausgabe analysierte.

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

Das Ausführen von stat außerhalb von Python vom Terminal (OS X) ergab Folgendes:

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

... wobei die vierte datetime die Dateierstellung ist (anstelle der ctime-Änderungszeit, wie in anderen Kommentaren angegeben).

kmarchand
quelle
13
-1: Das Parsen einer für Menschen bestimmten Ausgabe eines Shell-Befehls ist eine sehr schlechte Idee. Und dieser Befehl ist nicht einmal kreuzkompatibel.
MestreLion