Jak uzyskać datę / godzinę utworzenia i modyfikacji pliku w Pythonie?


932

Mam skrypt, który musi wykonać pewne czynności w oparciu o daty utworzenia i modyfikacji pliku, ale musi działać w systemach Linux i Windows .

Jaki jest najlepszy międzyplatformowy sposób na tworzenie i modyfikowanie plików date/timesw Pythonie ?


57
Nie można uzyskać czasu tworzenia pliku na wiele platform. Zobacz docs.python.org/library/os.path.html#os.path.getctime
— Glyph

Odpowiedzi:


620

Uzyskiwanie jakiejś daty modyfikacji na wiele platform jest łatwe - wystarczy zadzwonić, a otrzymasz uniksowy znacznik czasu, kiedy plik był ostatnio modyfikowany.os.path.getmtime(path)path

Z drugiej strony, uzyskiwanie dat utworzenia plików jest skomplikowane i zależne od platformy, różni się nawet między trzema dużymi systemami operacyjnymi:

Podsumowując, kod dla wielu platform powinien wyglądać mniej więcej tak ...

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
Zrobiłem co w mojej mocy, aby zebrać to w całość (i spędziłem kilka godzin na badaniu procesu) i jestem pewien, że jest to co najmniej bardziej poprawne niż odpowiedzi, które tu były wcześniej, ale to jest naprawdę trudny temat i „ d doceniamy wszelkie poprawki, wyjaśnienia lub inne informacje, które ludzie mogą zaoferować. W szczególności chciałbym skonstruować sposób dostępu do tych danych na ext4dyskach pod Linuksem i chciałbym dowiedzieć się, co się dzieje, gdy Linux odczytuje pliki napisane przez Windows lub odwrotnie, biorąc pod uwagę, że używają one st_ctimeinaczej.
— Mark Amery

25
Szczerze mówiąc, czas tworzenia pliku jest zwykle dość bezużyteczny. Kiedy otwierasz istniejący plik do zapisu w trybie "w", nie zastępuje go, po prostu otwiera istniejący plik i obcina go. Mimo że zawartość pliku jest całkowicie niezwiązana z tym, co miał podczas tworzenia, nadal można powiedzieć, że plik został „utworzony” na długo przed bieżącą wersją. I na odwrót, redaktorzy używający zamiany atomowej podczas zapisywania (oryginalny plik jest zastępowany nowym plikiem tymczasowym w toku) wyświetlałby późniejszą datę utworzenia, nawet jeśli usunąłeś tylko jeden znak. Użyj czasu modyfikacji, nie puszczaj gruba na czas tworzenia.
— ShadowRanger

3
Po wielu latach wreszcie znalazłem zastosowanie do tworzenia plików! Piszę kod, aby sprawdzić konwencję nazewnictwa plików w niektórych katalogach, więc przede wszystkim chcę rozważyć pliki, które zostały nazwane po utworzeniu konwencji. Zastąpienie całej zawartości (mtime) nie ma znaczenia: jeśli już tam była, to jest dziadek.
— Steve Jessop

1
Cześć Mark. Proponuję uproszczenie. W systemie Linux zwracanie stat.st_ctimejest bardziej istotne, ponieważ w wielu przypadkach czasem ostatniej zmiany metadanych może być czas utworzenia (przynajmniej ctimebliższy rzeczywistemu czasowi tworzenia niż mtime). Dlatego możesz po prostu zastąpić swój fragment stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Co myślisz? Pozdrawiam
— olibre,

4
@olibre „przynajmniej ctime jest bliższy rzeczywistemu czasowi tworzenia niż mtime” - nie, nie jest; to stwierdziłem kilka razy, ale jest to całkowicie nieprawda. Chyba że ręcznie pomieszane z wartościami w swojej węzła, ctimezawsze powinien być równy lub później niż mtime, ponieważ mtimezmiana powoduje to ctimezmianę (bo mtimesam jest uważany za „metadane”). Zobacz stackoverflow.com/a/39521489/1709587, gdzie podam przykładowy kod ilustrujący to.
— Mark Amery

676

Masz kilka możliwości. Po pierwsze możesz użyć funkcji os.path.getmtimei 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)))

Inną opcją jest użycie 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))

Uwaga : ctime()nie nie odnoszą się do czasu utworzenia na systemów uniksowych, ale raczej ostatni raz dane iwęzłów zmieniło. (podziękowania dla kojiro za wyjaśnienie tego faktu w komentarzach poprzez podanie linku do interesującego posta na blogu)


169
Na wypadek, gdyby ktoś pominął komentarz @ Glypha do pytania, ctime nie oznacza czasu tworzenia w systemach POSIX . Zastanawiam się, ile osób przeszukało ten post w ciągu ostatnich trzech lat i napisało błędny kod.
— kojiro,

16
Pamiętaj, że pierwszy przykład podaje ciąg znaków, a nie datę / godzinę lub liczbę.
— gak

1
@kojiro blogu już związana może być bardziej wyraźne, że na Unix plik użytkownika ctimezostanie zaktualizowany, gdy mtimerobi (ponieważ mtimejest „metadane”), a więc ctimejest zwykle zawsze równa lub przedmtime . Traktowanie ctimejak czas „stworzony” nie ma zatem żadnego sensu. -1!
— Mark Amery

Twoja pierwsza opcja zwraca te same wyniki zarówno dla utworzenia pliku, jak i ostatniej modyfikacji! Last modified: Fri Jan 31 11:08:13 2020i Created: Fri Jan 31 11:08:13 2020na Linux Ubuntu 16.04!
— Färid Alijani

Odkryłem, że time.ctime(os.path.getmtime(file))zwraca 2 typy ciągów, w zależności od tego, czy plik został zmodyfikowany przez system, czy przez użytkownika. Jeśli został zmodyfikowany przez system, łańcuch będzie zawierał 2 spacje między miesiącem a dniem. Nie wiem dlaczego
— Matteo Antolini

376

Najlepszą funkcją do tego celu jest os.path.getmtime () . To po prostu wykorzystuje os.stat(filename).st_mtime.

Moduł datetime jest najlepszym manipulowaniem znacznikami czasu, więc datę modyfikacji można uzyskać jako datetimeobiekt taki jak ten:

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

Przykład użycia:

>>> 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
Ta odpowiedź jest również trochę błędna. getmtimejest najbliższą rzeczą dostępną w systemie Unix (gdzie uzyskanie dat utworzenia nie jest możliwe), ale zdecydowanie nie jest najlepszą funkcją do użycia w systemie Windows, gdzie ctimejest czas utworzenia.
— Mark Amery

3
@MarkAmery - Ta odpowiedź jest wyraźnie oznaczona jako dotycząca czasu modyfikacji.
— ArtOfWarfare

47

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

edit: W nowszym kodzie powinieneś prawdopodobnie użyć os.path.getmtime () (dzięki Christian Oudard),
ale zwróć uwagę, że zwraca zmiennoprzecinkową wartość time_t z ułamkiem sekund (jeśli twój system to obsługuje)


44
Os.path.getmtime () jest stworzony do tego i jest prostszy.
— Christian Oudard

5
Klauzula „w nowym kodzie” tutaj jest nieco myląca. os.path.getmtime()istnieje od czasu wydania Python 1.5.2 (patrz stare dokumenty ), wydanego zanim straciłem większość zębów mlecznych i prawie dekadę przed napisaniem oryginalnej wersji tej odpowiedzi.
— Mark Amery

39

Istnieją dwie metody uzyskania czasu mod, os.path.getmtime () lub os.stat (), ale ctime nie jest wiarygodny na różnych platformach (patrz poniżej).

os.path.getmtime ()

getmtime ( ścieżka )
Zwraca czas ostatniej modyfikacji ścieżki. Wartość zwracana to liczba podająca liczbę sekund od epoki (patrz moduł czasu). Podnieś os.error, jeśli plik nie istnieje lub jest niedostępny. Nowości w wersji 1.5.2. Zmieniono w wersji 2.3: Jeśli os.stat_float_times () zwraca True, wynikiem jest liczba zmiennoprzecinkowa.

os.stat ()

stat ( ścieżka )
Wykonaj wywołanie systemowe stat () na podanej ścieżce. Zwracana wartość to obiekt, którego atrybuty odpowiadają elementom struktury statystyki, a mianowicie: st_mode (bity ochronne), st_ino (numer i-węzła), st_dev (urządzenie), st_nlink (liczba twardych dowiązań), st_uid (identyfikator użytkownika właściciela ), st_gid (identyfikator grupy właściciela), st_size (rozmiar pliku, w bajtach), st_atime (czas ostatniego dostępu), st_mtime (czas ostatniej modyfikacji treści), st_ctime (zależny od platformy; czas ostatniej zmiany metadanych w systemie Unix lub czas utworzenia w systemie Windows) :

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

W powyższym przykładzie użyjesz statinfo.st_mtime lub statinfo.st_ctime, aby uzyskać odpowiednio mtime i ctime.


13

W Pythonie 3.4 i nowszych można użyć zorientowanego obiektowo interfejsu modułu pathlib , który zawiera opakowania dla większości modułów systemu operacyjnego . Oto przykład pobierania statystyk plików.

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

Aby uzyskać więcej informacji o tym os.stat_result, co zawiera, zapoznaj się z dokumentacją . Dla potrzebnego czasu modyfikacji 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)

Jeśli chcesz czas utworzenia w systemie Windows lub najnowszą zmianę metadanych w systemie Unix, możesz użyć fname.stat().st_ctime:

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

Ten artykuł zawiera bardziej pomocne informacje i przykłady dotyczące modułu pathlib.


11

os.statzwraca nazwaną krotkę z atrybutami st_mtimei st_ctime. Czas modyfikacji jest st_mtimena obu platformach; niestety w systemie Windows ctimeoznacza „czas utworzenia”, podczas gdy w systemie POSIX oznacza „czas zmiany”. Nie znam żadnego sposobu na uzyskanie czasu tworzenia na platformach POSIX.


Oto więcej o tagowanych krotkach: stackoverflow.com/questions/2970608/... Działają jak krotki, ale spróbuj dir(..)jednego. Np.dir(os.stat(os.listdir('.')[0]))
— Jewgienij Siergiejew

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

odciski

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: Podobnie jak w przypadku innych odpowiedzi, nie da ci to czasu utworzenia pliku w systemie Windows (który ponownie nie jest nawet wspomniany w odpowiedzi).
— ntninja

@ntninja jesteś tego pewien? Używam tylko systemu Windows i to absolutnie działa. napisałem ten skrypt na początku 2015 roku. Uważam, że był on bardziej przejrzysty, od razu do rzeczy, kompletny i zrozumiały dla innych tutaj. (które przypadkiem postanowiłem poszukać tutaj zamiast moich starych skryptów, tylko że nie było nic nowego. nie ... tak jest)
— Puddle

Och, chciałem powiedzieć „… to nie da ci czasu na utworzenie pliku, chyba że jesteś w systemie Windows”. Przepraszam! Faktem jest, że ta odpowiedź nie jest przenośna i nie wspomina o tym fakcie. (Przykład danych wyjściowych w systemie Linux: pastebin.com/50r5vGBE )
— ntninja

@ntnja, to powiesz wszystkim innym?
— Puddle

Zostawiłem już kilka innych komentarzy, a wkrótce opublikuję odpowiedź, która działa również na (niedawnym) Linuksie. Ale tak naprawdę jedyną wadą w swoim poście jest to, że odpowiedź tylko dla systemu Windows nie wspomina o tym fakcie. W pytaniu OP nawet konkretnie poprosił o rozwiązanie kompatybilne z Windows i Linux. Dlatego uważam, że bardzo pomocne byłoby dodanie tego „szczegółu” gdzieś na górze, aby ludzie nie byli wprowadzani w błąd, myśląc, że ctime jest tym, czego szukają na wielu platformach.
— ntninja

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

-1: Jak wspomniano w innym miejscu, nie da ci to czasu utworzenia pliku, chyba że korzystasz z systemu Windows (którego odpowiedź nawet nie wspomina!).
— ntninja

0

Jeśli podążanie za dowiązaniami symbolicznymi nie jest ważne, możesz również użyć os.lstatwbudowanego.

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

To da czas ostatniego czytania (przynajmniej na Unixie), co zdecydowanie nie jest tym, o co proszono.
— Mark Amery

0

Warto spojrzeć na crtimebibliotekę, która implementuje międzyplatformowy dostęp do czasu tworzenia pliku.

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
Zdecydowanie odradzam to: używa debugfsw Linuksie, który z definicji jest niestabilny, wymaga dostępu do konta root na najwyższym poziomie i praktycznie w każdym aspekcie jest jedną z rzeczy, o których zawsze ostrzegała cię twoja matka. (Ale tak, to prawdopodobnie działa, jeśli naprawdę jesteś zdesperowany i zdarza ci się być prawdziwym superużytkownikiem w systemie bez bezpiecznego rozruchu…)
— ntninja

@ntninja Prawdopodobnie nigdy nie użyję go w produkcji, ale może być przydatny do „skryptów domowych”.
— Delgan

-2

os.statobejmuje czas utworzenia. Po prostu nie ma definicji st_anything dla elementu, os.stat()który zawiera czas.

Spróbuj tego:

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

Porównaj to ze swoją datą utworzenia w pliku w ls -lah

Powinny być takie same.


6
Źle! os.stat ('feedparser.py') [8] odnosi się do st_mtime, a nie do czasu utworzenia. Proszę zapoznać się z dokumentacją: docs.python.org/library/os.html#os.stat
— millerdev

4
Proszę użyć .st_ctime zamiast brzydkich liczb [8].
— guettli,

-3

Byłem w stanie uzyskać czas tworzenia na posix, uruchamiając komendę systemową statystyki i analizując dane wyjściowe.

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

Uruchomienie statystyki poza pythonem z terminala (OS X) zwróciło:

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

... gdzie czwartym czasem danych jest tworzenie pliku (zamiast czasu zmiany ctime, jak zauważono w innych komentarzach).


13
-1: Parsowanie wyjścia przeznaczonego dla ludzi z polecenia powłoki jest bardzo złym pomysłem. To polecenie nie jest nawet kompatybilne krzyżowo.
— MestreLion,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.