¿Cómo obtener la fecha / hora de creación y modificación de archivos en Python?

934

Tengo un script que necesita hacer algunas cosas en función de la creación de archivos y las fechas de modificación, pero tiene que ejecutarse en Linux y Windows .

¿Cuál es la mejor forma multiplataforma para obtener la creación y modificación de archivos date/timesen Python ?

Mark Biek
fuente
57
No puede obtener el tiempo de creación de archivos de una manera multiplataforma. Ver docs.python.org/library/os.path.html#os.path.getctime
Glyph

Respuestas:

621

Obtener algún tipo de fecha de modificación en una plataforma multiplataforma es fácil: solo llame y obtendrá la marca de tiempo de Unix de cuándo se modificó por última vez el archivo .os.path.getmtime(path)path

Obtener fechas de creación de archivos , por otro lado, es complicado y depende de la plataforma, y ​​difiere incluso entre los tres grandes sistemas operativos:

Poniendo todo esto junto, el código multiplataforma debería verse así ...

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
fuente
99
He hecho todo lo posible para unir esto (y pasé unas horas investigando en el proceso), y estoy seguro de que es al menos más correcto que las respuestas que estaban aquí anteriormente, pero este es un tema realmente difícil y yo ' Apreciaría cualquier corrección, aclaración u otro aporte que la gente pueda ofrecer. En particular, me gustaría construir una forma de acceder a estos datos en ext4unidades con Linux, y me gustaría saber qué sucede cuando Linux lee archivos escritos por Windows, o viceversa, dado que se usan de manera st_ctimediferente.
Mark Amery
25
Francamente, el tiempo de creación de archivos suele ser bastante inútil. Cuando abre un archivo existente para escribir con modo "w", no lo reemplaza, solo abre el archivo existente y lo trunca. A pesar de que el contenido del archivo no tiene relación alguna con lo que tenía en la creación, aún le dirían que el archivo fue "creado" mucho antes de la versión actual. Por el contrario, los editores que usan el reemplazo atómico al guardar (el archivo original se reemplaza por un nuevo archivo temporal de trabajo en progreso) mostrarían una fecha de creación más reciente, incluso si acaba de eliminar un carácter. Use el tiempo de modificación, no busque el tiempo de creación.
ShadowRanger
3
¡Después de muchos años, finalmente encontré un uso para el tiempo de creación de archivos! Estoy escribiendo código para verificar una convención de nomenclatura de archivos en ciertos directorios, por lo que antes que nada quiero considerar los archivos que se nombraron por primera vez después de que se instituyó la convención. Reemplazar todo el contenido (mtime) es irrelevante: si ya estaba allí, está protegido.
Steve Jessop
1
Hola, Mark. Propongo una simplificación. En Linux, regresar stat.st_ctimees más pertinente porque, en muchos casos, el momento del último cambio de metadatos puede ser el tiempo de creación (al menos ctimeestá más cerca del tiempo de creación real que mtime). Por lo tanto, simplemente puede reemplazar su fragmento por stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. ¿Qué piensas? Saludos
olibre
44
@olibre "al menos ctime está más cerca del tiempo de creación real que mtime" - no, no lo está; Esto es algo que he visto varias veces, pero es totalmente falso. A menos que haya manipulado manualmente los valores en su inodo, ctimesiempre debe ser igual o posterior a mtime, porque un mtimecambio provoca un ctimecambio (porque el mtimemismo se considera "metadatos"). Consulte stackoverflow.com/a/39521489/1709587 donde proporciono un código de ejemplo para ilustrar esto.
Mark Amery
676

Usted tiene un par de opciones. Por un lado, puede usar las funciones os.path.getmtimey 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)))

Su otra opción es usar 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()no se refiere al tiempo de creación en los sistemas * nix, sino a la última vez que cambiaron los datos del inodo. (gracias a kojiro por aclarar ese hecho en los comentarios al proporcionar un enlace a una publicación de blog interesante)

Bryan Oakley
fuente
169
En caso de que alguien pierda el comentario de @ Glyph a la pregunta, ctime no significa tiempo de creación en los sistemas POSIX . Me pregunto cuántas personas han leído esta publicación en los últimos tres años y han escrito código con errores.
kojiro
16
Tenga en cuenta que el primer ejemplo le proporciona una cadena, no una fecha, hora o número.
gak
1
@kojiro la entrada de blog que ha enlazado a puede ser más explícito que en Unix un archivo del ctimeque se actualiza cada vez que la mtimehace (ya que el mtimees "metadatos"), por lo que el ctimenormalmente es siempre igual a o por delante de la mtime. Tratar ctimecomo tiempo "creado" no tiene ningún sentido. -1!
Mark Amery
¡Su primera opción devuelve los mismos resultados para la creación de archivos y la última modificación! Last modified: Fri Jan 31 11:08:13 2020y Created: Fri Jan 31 11:08:13 2020en Linux Ubuntu 16.04!
Färid Alijani
Descubro que time.ctime(os.path.getmtime(file))devuelve 2 tipos de cadenas, dependiendo de si el archivo ha sido modificado por el sistema o por el usuario. Si ha sido modificado por el sistema, la cadena tendrá 2 espacios entre el mes y el día. No sé por qué
Matteo Antolini
376

La mejor función a utilizar para esto es os.path.getmtime () . Internamente, esto solo usa os.stat(filename).st_mtime.

El módulo de fecha y hora es la mejor marca de tiempo de manipulación, por lo que puede obtener la fecha de modificación como un datetimeobjeto como este:

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

Ejemplo de uso:

>>> 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
fuente
1
Esta respuesta también es un poco incorrecta. getmtimees lo más cercano disponible en Unix (donde no es posible obtener fechas de creación), pero definitivamente no es la mejor función para usar en Windows, donde ctimees un tiempo de creación.
Mark Amery
3
@ MarkAmery: esta respuesta está claramente etiquetada como solo sobre el tiempo de modificación.
ArtOfWarfare
47

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

editar: en el código más reciente, probablemente debería usar os.path.getmtime () (gracias Christian Oudard)
pero tenga en cuenta que devuelve un valor de coma flotante de time_t con fracción de segundo (si su sistema operativo lo admite)

Martin Beckett
fuente
44
os.path.getmtime () está hecho para esto y es más simple.
Christian Oudard el
55
La cláusula "en código más reciente" aquí es un poco engañosa. os.path.getmtime()ha existido desde Python 1.5.2 (ver los documentos antiguos ), lanzado antes de que perdiera la mayoría de mis dientes de leche y casi una década antes de que escribiera la versión original de esta respuesta.
Mark Amery
39

Hay dos métodos para obtener el tiempo de modificación, os.path.getmtime () o os.stat (), pero ctime no es confiable multiplataforma (ver más abajo).

os.path.getmtime ()

getmtime ( ruta )
Devuelve la hora de la última modificación de ruta. El valor de retorno es un número que proporciona el número de segundos desde la época (consulte el módulo de tiempo). Levante os.error si el archivo no existe o es inaccesible. Nuevo en la versión 1.5.2. Modificado en la versión 2.3: si os.stat_float_times () devuelve True, el resultado es un número de coma flotante.

os.stat ()

stat ( ruta )
Realiza una llamada al sistema stat () en la ruta dada. El valor de retorno es un objeto cuyos atributos corresponden a los miembros de la estructura estadística, a saber: st_mode (bits de protección), st_ino (número de inodo), st_dev (dispositivo), st_nlink (número de enlaces duros), st_uid (ID de usuario del propietario) ), st_gid (ID de grupo del propietario), st_size (tamaño del archivo, en bytes), st_atime (hora del acceso más reciente), st_mtime (hora de la modificación de contenido más reciente), st_ctime (depende de la plataforma; hora del cambio de metadatos más reciente en Unix, o el momento de la creación en Windows) :

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

En el ejemplo anterior, usaría statinfo.st_mtime o statinfo.st_ctime para obtener mtime y ctime, respectivamente.

Arrendajo
fuente
13

En Python 3.4 y versiones posteriores, puede usar la interfaz del módulo pathlib orientada a objetos que incluye envoltorios para gran parte del módulo os. Aquí hay un ejemplo de cómo obtener las estadísticas del archivo.

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

Para obtener más información sobre lo que os.stat_resultcontiene, consulte la documentación . Para el tiempo de modificación que desee 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)

Si desea el tiempo de creación en Windows, o el cambio de metadatos más reciente en Unix, usaría fname.stat().st_ctime:

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

Este artículo tiene más información útil y ejemplos para el módulo pathlib.

Steven C. Howell
fuente
11

os.statdevuelve una tupla con nombre con st_mtimey st_ctimeatributos. El tiempo de modificación es st_mtimeen ambas plataformas; desafortunadamente, en Windows ctimesignifica "tiempo de creación", mientras que en POSIX significa "tiempo de cambio". No conozco ninguna forma de obtener el tiempo de creación en las plataformas POSIX.

mithrandi
fuente
Aquí hay más información sobre las tuplas etiquetadas: stackoverflow.com/questions/2970608/... Funcionan como tuplas, pero prueba dir(..)una. Por ejemplodir(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))

huellas dactilares

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
Charco
fuente
-1: al igual que otras respuestas, esto no le dará el tiempo de creación del archivo en Windows (que, una vez más, ni siquiera se menciona en la respuesta).
ntninja
@ntninja, ¿estás seguro de eso? Solo uso Windows y esto funciona absolutamente. Escribí este guión a principios de 2015. Me parece más claro, directo al grano, completo y explicativo que otros aquí. (que decidí buscar aquí en lugar de mis viejos guiones en caso de que hubiera algo nuevo. No ... esta es la forma)
Charco
Oh, quise decir "... esto no te dará el tiempo de creación del archivo, a menos que estés en Windows". ¡Lo siento! El hecho es que esta respuesta no es portátil y no menciona este hecho. (Ejemplo de salida en Linux: pastebin.com/50r5vGBE )
ntninja
@ntninja, ¿vas a decirle a todos los demás entonces?
Charco
Ya dejé algunos otros comentarios aquí y pronto publicaré una respuesta que funcione en Linux (reciente). Pero realmente, lo único incorrecto en su publicación es que es una respuesta solo de Windows que no menciona este hecho. En la pregunta, OP incluso solicitó específicamente una solución compatible con Windows y Linux. Como tal, creo que sería muy útil si agregaras este "detalle" en algún lugar en la parte superior, para que las personas no se engañen al pensar que ctime es lo que buscan cuando se dirigen a múltiples plataformas.
ntninja
2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 
desmontado
fuente
-1: Como se mencionó en otra parte, esto no le dará el tiempo de creación del archivo, a menos que esté en Windows (¡que la respuesta ni siquiera menciona!).
ntninja
0

Si seguir enlaces simbólicos no es importante, también puede usar el os.lstatbuiltin incorporado.

>>> 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
Bajo Kian Seong
fuente
Esto le dará el tiempo de la última lectura (al menos en Unix), que definitivamente no es lo que se solicitó.
Mark Amery
0

Puede valer la pena echar un vistazo a la crtimebiblioteca que implementa el acceso multiplataforma al tiempo de creación de archivos.

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
fuente
1
No recomiendo esto: utiliza debugfsen Linux, que por definición es inestable, requiere acceso de raíz de nivel superior para todo y en casi todos los aspectos tiende a ser una de las cosas que su madre siempre le advirtió. (Pero sí, probablemente funcione si estás realmente desesperado y eres el superusuario real en un sistema sin arranque seguro ...)
ntninja
@ntninja Probablemente nunca lo usaría en producción tampoco, pero puede ser útil para "guiones caseros".
Delgan
-2

os.statincluye el tiempo de creación. Simplemente no hay una definición de st_anything para el elemento os.stat()que contiene el tiempo.

Así que prueba esto:

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

Compare eso con su fecha de creación en el archivo en ls -lah

Deberían ser iguales.

varilla
fuente
66
¡Incorrecto! os.stat ('feedparser.py') [8] se refiere a st_mtime, no a la hora de creación. Consulte la documentación: docs.python.org/library/os.html#os.stat
millerdev
44
Utilice .st_ctime en lugar de números feos [8].
guettli
-3

Pude obtener el tiempo de creación en posix ejecutando el comando stat del sistema y analizando la salida.

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

La ejecución de estadísticas fuera de Python desde la Terminal (OS X) devolvió:

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

... donde la cuarta fecha y hora es la creación del archivo (en lugar de la hora de cambio de ctime como se señaló en otros comentarios).

kmarchand
fuente
13
-1: Analizar una salida para humanos desde un comando de shell es una muy mala idea. Y este comando ni siquiera es compatible.
MestreLion