Como obter data / hora de criação e modificação de arquivo em Python?

934

Eu tenho um script que precisa fazer algumas coisas com base nas datas de criação e modificação de arquivos, mas que deve ser executado no Linux e Windows .

Qual é a melhor maneira de plataforma cruzada para obter criação e modificação de arquivos date/timesno Python ?

Mark Biek
fonte
57
Você não pode obter o tempo de criação do arquivo de uma forma multiplataforma. Consulte docs.python.org/library/os.path.html#os.path.getctime
Glyph

Respostas:

621

É fácil obter algum tipo de data de modificação em uma plataforma cruzada - basta ligar e você receberá o carimbo de data e hora do Unix de quando o arquivo foi modificado pela última vez.os.path.getmtime(path)path

A obtenção de datas de criação de arquivo , por outro lado, é complicada e depende da plataforma, diferindo mesmo entre os três grandes sistemas operacionais:

Juntando tudo isso, o código de plataforma cruzada deve se parecer com isso ...

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
fonte
9
Eu fiz o meu melhor para juntar isso (e passei algumas horas pesquisando no processo), e tenho certeza de que é pelo menos mais correto do que as respostas que estavam aqui anteriormente, mas esse é um tópico muito difícil e eu ' d aprecio quaisquer correções, esclarecimentos ou outras informações que as pessoas possam oferecer. Em particular, gostaria de construir uma maneira de acessar esses dados em ext4unidades no Linux, e gostaria de saber o que acontece quando o Linux lê arquivos escritos pelo Windows, ou vice-versa, uma vez que eles usam de maneira st_ctimediferente.
Mark Amery
25
Francamente, o tempo de criação do arquivo é geralmente bastante inútil. Quando você abre um arquivo existente para gravação no modo "w", ele não está sendo substituído, ele apenas abre o arquivo existente e o trunca. Mesmo que o conteúdo do arquivo não esteja completamente relacionado ao que havia na criação, você ainda seria informado de que o arquivo foi "criado" muito antes da versão atual. Por outro lado, os editores que usam substituição atômica ao salvar (o arquivo original é substituído por um novo arquivo temporário de trabalho em andamento) mostram uma data de criação mais recente, mesmo se você tiver excluído apenas um caractere. Use o tempo de modificação, não faça grub pelo tempo de criação.
ShadowRanger
3
Depois de muitos anos, finalmente encontrei um uso para o tempo de criação do arquivo! Estou escrevendo um código para verificar uma convenção de nomenclatura de arquivos em determinados diretórios; primeiro, quero considerar os arquivos que foram nomeados primeiro após a instituição da convenção. Substituir todo o conteúdo (mtime) é irrelevante: se ele já estava lá, então ele está adquiridos no.
Steve Jessop
1
Olá Mark. Eu proponho uma simplificação. No Linux, o retorno stat.st_ctimeé mais pertinente porque, em muitos casos, o tempo de última alteração de metadados pode ser a hora de criação (pelo menos ctimeé mais próxima ao real tempo de criação do que mtime). Portanto, você pode simplesmente substituir seu snippet por stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. O que você acha? Cheers
olibre 7/08
4
@olibre "pelo menos o ctime está mais próximo do tempo real de criação do que o mtime" - não, não é; isso é algo que eu já vi várias vezes, mas é totalmente falso. A menos que você tenha mexido manualmente com os valores em seu inode, ctimesempre deve ser igual ou posterior a mtime, porque uma mtimealteração causa uma ctimealteração (porque mtimeela mesma é considerada "metadados"). Consulte stackoverflow.com/a/39521489/1709587, onde forneço alguns códigos de exemplo para ilustrar isso.
Mark Amery
676

Você tem algumas opções. Por um lado, você pode usar as funções 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)))

Sua outra opção é 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()não se refere ao horário de criação nos sistemas * nix, mas na última vez em que os dados do inode foram alterados. (obrigado a kojiro por deixar esse fato mais claro nos comentários, fornecendo um link para um post interessante no blog)

Bryan Oakley
fonte
169
Caso alguém perca o comentário do @ Glyph na pergunta, ctime não significa tempo de criação nos sistemas POSIX . Gostaria de saber quantas pessoas vasculharam este post nos últimos três anos e continuaram a escrever código de buggy.
Kojiro
16
Lembre-se de que o primeiro exemplo fornece uma sequência de caracteres, não uma data / hora ou número.
gak
1
@kojiro o post que você tiver vinculado a poderia ser mais explícito que em Unix um arquivo do ctimeé atualizado sempre que o mtimefaz (uma vez que o mtimeé "metadados"), e assim o ctimeé normalmente sempre igual a ou antes de o mtime. Tratar ctimecomo tempo "criado", portanto, não faz nenhum sentido. -1!
Mark Amery
Sua primeira opção retorna os mesmos resultados para a criação do arquivo e a última modificação! Last modified: Fri Jan 31 11:08:13 2020e Created: Fri Jan 31 11:08:13 2020no Linux Ubuntu 16.04!
Färid Alijani em
Descobri que time.ctime(os.path.getmtime(file))retorna 2 tipos de strings, dependendo se o arquivo foi modificado pelo sistema ou pelo usuário. Se tiver sido modificado pelo sistema, a sequência terá 2 espaços entre o mês e o dia. Não sei porquê
Matteo Antolini
376

A melhor função a ser usada para isso é os.path.getmtime () . Internamente, isso apenas usa os.stat(filename).st_mtime.

O módulo datetime é o melhor registro de data e hora de manipulação, para que você possa obter a data da modificação como um datetimeobjeto como este:

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

Exemplo 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
fonte
1
Esta resposta também está um pouco errada. getmtimeé a coisa mais próxima disponível no Unix (onde a obtenção de datas de criação não é possível), mas definitivamente não é a melhor função a ser usada no Windows, onde ctimeé o momento da criação.
Mark Amery
3
@ MarkAmery - Esta resposta está claramente rotulada como sendo apenas sobre o tempo de modificação.
ArtOfWarfare
47

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

edit: No código mais recente, você provavelmente deve usar os.path.getmtime () (obrigado Christian Oudard)
mas observe que ele retorna um valor de ponto flutuante de time_t com fração de segundos (se o seu sistema operacional suportar)

Martin Beckett
fonte
44
os.path.getmtime () é feito para isso, e mais simples.
9409 Christian Oudard
5
A cláusula "no código mais recente" aqui é um pouco enganadora. os.path.getmtime()existe desde o Python 1.5.2 (consulte os documentos antigos ), lançado antes que eu perdesse a maioria dos meus dentes de leite e quase uma década antes de você escrever a versão original desta resposta.
Mark Amery
39

Existem dois métodos para obter o horário da modificação, os.path.getmtime () ou os.stat (), mas o ctime não é confiável entre plataformas (veja abaixo).

os.path.getmtime ()

getmtime ( caminho )
Retorna a hora da última modificação do caminho. O valor de retorno é um número que indica o número de segundos desde a época (consulte o módulo de tempo). Aumente o arquivo os.error se o arquivo não existir ou estiver inacessível. Novo na versão 1.5.2. Alterado na versão 2.3: Se os.stat_float_times () retornar True, o resultado será um número de ponto flutuante.

os.stat ()

stat ( caminho )
Execute uma chamada de sistema stat () no caminho especificado. O valor de retorno é um objeto cujos atributos correspondem aos membros da estrutura stat, a saber: st_mode (bits de proteção), st_ino (número de inode), st_dev (dispositivo), st_nlink (número de links físicos), st_uid (ID do usuário do proprietário ), st_gid (ID do grupo do proprietário), st_size (tamanho do arquivo, em bytes), st_atime (hora do acesso mais recente), st_mtime (hora da modificação do conteúdo mais recente), st_ctime (dependente da plataforma; hora da alteração mais recente dos metadados) no Unix ou no momento da criação no Windows) :

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

No exemplo acima, você usaria statinfo.st_mtime ou statinfo.st_ctime para obter o mtime e o ctime, respectivamente.

Jay
fonte
13

No Python 3.4 e acima, você pode usar a interface do módulo pathlib orientada a objetos , que inclui wrappers para grande parte do módulo os. Aqui está um exemplo de como obter as estatísticas do arquivo.

>>> 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 mais informações sobre o que os.stat_resultcontém, consulte a documentação . Para o tempo de modificação que você deseja 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 você quiser o horário de criação no Windows ou a alteração mais recente dos metadados no Unix, use fname.stat().st_ctime:

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

Este artigo tem informações e exemplos mais úteis para o módulo pathlib.

Steven C. Howell
fonte
11

os.statretorna uma tupla nomeada com st_mtimee st_ctimeatributos. O tempo de modificação é st_mtimenas duas plataformas; infelizmente, no Windows, ctimesignifica "hora da criação", enquanto no POSIX, significa "hora da mudança". Não conheço nenhuma maneira de obter o tempo de criação nas plataformas POSIX.

mithrandi
fonte
Aqui está mais sobre tuplas marcadas: stackoverflow.com/questions/2970608/… Eles funcionam como tuplas, mas tente dir(..)uma. Por exemplodir(os.stat(os.listdir('.')[0]))
Evgeni Sergeev 16/10
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))

impressões

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
Poça
fonte
-1: O mesmo que as outras respostas, isso não fornece o tempo de criação do arquivo no Windows (que, mais uma vez, nem é mencionado na resposta).
ntninja 8/01
@ntninja você tem certeza disso? Eu só uso o Windows e isso absolutamente funciona. Eu escrevi esse script no início de 2015. Acho que era mais claro, direto ao ponto, completo e autoexplicativo do que outros aqui. (que por acaso decidi procurar aqui em vez de meus scripts antigos, apenas porque havia algo novo. não ... esse é o caminho)
Puddle
Ah, eu queria dizer "... isso não fornecerá o tempo de criação do arquivo, a menos que você esteja no Windows". Desculpa! Fato permanece que esta resposta não é portátil e não menciona esse fato. (Exemplo de saída no Linux: pastebin.com/50r5vGBE )
ntninja
@ntninja você vai contar para todo mundo então?
Puddle
Já deixei alguns outros comentários aqui e vou postar uma resposta que funciona no Linux (recente) também em breve. Mas, na verdade, a única coisa errada na sua postagem é que é a resposta apenas do Windows que não menciona esse fato. Na questão, o OP ainda solicitou especificamente uma solução compatível com Windows e Linux. Como tal, acho que seria muito útil se você adicionasse esse "detalhe" em algum lugar no topo, para que as pessoas não se enganem ao pensar que ctime é o que procuram quando segmentam várias plataformas.
ntninja 11/01
2
>>> import os
>>> os.stat('feedparser.py').st_mtime
1136961142.0
>>> os.stat('feedparser.py').st_ctime
1222664012.233
>>> 
desmontado
fonte
-1: Como mencionado em outro lugar, isso não fornecerá o tempo de criação do arquivo, a menos que você esteja no Windows (que a resposta nem sequer menciona!).
ntninja 8/01
0

Se os links simbólicos a seguir não forem importantes, você também poderá usar o os.lstatbuilt-in.

>>> 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
Baixo Kian Seong
fonte
Isso fornecerá o tempo da última leitura (pelo menos no Unix), que definitivamente não é o que foi solicitado.
Mark Amery
0

Vale a pena dar uma olhada na crtimebiblioteca que implementa o acesso entre plataformas ao tempo de criação do arquivo.

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
fonte
1
Aconselho veementemente contra isso: ele usa debugfsno Linux, que é por definição instável, requer acesso root de alto nível para tudo e, em quase todos os aspectos, tende a ser uma das coisas que sua mãe sempre o alertou. (Mas sim, provavelmente funcionará se você estiver realmente desesperado e for o verdadeiro superusuário de um sistema sem inicialização segura…)
ntninja
@ntninja Eu provavelmente nunca usaria na produção também, mas pode ser útil para "scripts domésticos".
Delgan 8/01
-2

os.statinclui o tempo de criação. Simplesmente não há definição de st_anything para o elemento deos.stat() que contém o tempo.

Então tente o seguinte:

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

Compare isso com a sua data de criação no arquivo em ls -lah

Eles deveriam ser os mesmos.

Cajado
fonte
6
Errado! os.stat ('feedparser.py') [8] refere-se a st_mtime, não à hora da criação. Consulte a documentação: docs.python.org/library/os.html#os.stat
millerdev
4
Por favor, use .st_ctime em vez de números feios [8].
amigos estão dizendo sobre guettli
-3

Consegui obter tempo de criação no posix executando o comando stat do sistema e analisando a saída.

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

A execução do stat fora do python do Terminal (OS X) retornou:

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

... onde a quarta data e hora é a criação do arquivo (em vez da hora de alteração do ctime, como outros comentários observados).

kmarchand
fonte
13
-1: Analisando uma saída significou para os seres humanos a partir de um comando shell é uma muito má ideia. E esse comando nem é compatível com outras versões.
MestreLion