Как узнать дату и время создания и изменения файла в Python?


935

У меня есть скрипт, который должен делать некоторые вещи, основанные на датах создания и изменения файлов, но должен работать в Linux и Windows .

Какой лучший кроссплатформенный способ получить создание и изменение файлов date/timesв Python ?


57
Вы не можете получить время создания файла кросс-платформенным способом. См. Docs.python.org/library/os.path.html#os.path.getctime
— Glyph

Ответы:


622

Получить какую-то дату модификации кроссплатформенным способом легко - просто позвоните, и вы получите метку времени Unix, когда файл был последний раз изменен.os.path.getmtime(path)path

Получение дат создания файла , с другой стороны, зависит от платформы и зависит даже от трех больших ОС:

  • В Windows файл ctime(задокументированный по адресу https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ) хранит дату его создания. Вы можете получить доступ к этому в Python через os.path.getctime()или к .st_ctimeатрибуту результата вызова os.stat(). Это не будет работать в Unix, где в ctime последний раз менялись атрибуты или содержимое файла .
  • На Mac , как и на некоторых других Unix-системах, вы можете использовать .st_birthtimeатрибут результата вызова os.stat().
  • В Linux это в настоящее время невозможно, по крайней мере без написания расширения C для Python. Хотя некоторые файловые системы, обычно используемые в Linux , хранят даты создания (например, ext4хранят их в st_crtime), ядро ​​Linux не предлагает никакого доступа к ним ; в частности, структуры, которые он возвращает из stat()вызовов в C, начиная с последней версии ядра, не содержат никаких полей даты создания . Вы также можете видеть, что этот идентификатор в st_crtimeнастоящее время отсутствует в источнике Python . По крайней мере , если вы на ext4, данные в прикрепляются к дескрипторам в файловой системе, но нет удобного способа доступа к нему.

    Следующая лучшая вещь на Linux является доступ к файлу mtime, либо через os.path.getmtime()или в .st_mtimeатрибутеos.stat() результата. Это даст вам последний раз, когда содержимое файла было изменено, что может быть достаточно для некоторых случаев использования.

Собирая все это вместе, кросс-платформенный код должен выглядеть примерно так ...

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
Я приложил все усилия, чтобы сложить все вместе (и потратил несколько часов на изучение процесса), и я уверен, что это по крайней мере более правильно, чем ответы, которые были здесь ранее, но это действительно сложная тема, и я Буду признателен за любые исправления, разъяснения или другие материалы, которые могут предложить люди. В частности, я хотел бы создать способ доступа к этим данным на ext4дисках под Linux, и я хотел бы узнать, что происходит, когда Linux читает файлы, написанные Windows, или наоборот, учитывая, что они используют по- st_ctimeразному.
— Марк Амери

25
Честно говоря, время создания файла обычно довольно бесполезно. Когда вы открываете существующий файл для записи в режиме "w", он не заменяет его, он просто открывает существующий файл и усекает его. Даже если содержимое файла совершенно не связано с тем, что оно имело при создании, вам все равно сказали бы, что файл «создан» задолго до текущей версии. И наоборот, редакторы, использующие атомарную замену при сохранении (исходный файл заменяется новым временным файлом, находящимся в процессе выполнения), будут отображать более позднюю дату создания, даже если вы только что удалили один символ. Используйте время модификации, а не время для создания.
— ShadowRanger

3
Спустя много лет я наконец нашел применение времени создания файлов! Я пишу код для проверки соглашения об именовании файлов в определенных каталогах, поэтому прежде всего я хочу рассмотреть файлы, которые были впервые названы после того, как было установлено соглашение. Замена всего содержимого (mtime) не имеет значения: если он уже был там, значит, он в нем работает.
— Steve Jessop

1
Привет Марк. Я предлагаю упрощение. В Linux возврат stat.st_ctimeболее уместен, поскольку во многих случаях время последнего изменения метаданных может быть временем создания (по крайней мере ctime, ближе к реальному времени создания, чем mtime). Поэтому вы можете просто заменить свой фрагмент на stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Что вы думаете? Приветствия
— olibre

4
@olibre "по крайней мере ctime ближе к реальному времени создания, чем mtime" - нет, это не так; это то, что я видел, заявлено несколько раз, но это полностью неверно. Если вы не вручную перепутались со значениями в вашем иноду ctimeвсегда должна быть равна или позже , чем mtime, потому что mtimeизменение приводит к ctimeизменению (поскольку mtimeсам считается «метаданных»). См. Stackoverflow.com/a/39521489/1709587, где я приведу пример кода, чтобы проиллюстрировать это.
— Марк Эмери

676

У вас есть несколько вариантов. С одной стороны , вы можете использовать os.path.getmtimeи 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)))

Другой вариант - использовать 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))

Примечание : ctime()это не относится к времени создания на * NIX систем, а последний раз , когда данные индексных дескрипторов изменились. (спасибо Кодзиро за разъяснение этого факта в комментариях, предоставив ссылку на интересную запись в блоге)


169
На всякий случай, если кто-то пропустит комментарий @ Glyph к этому вопросу, ctime не означает время создания в системах POSIX . Интересно, сколько людей просмотрели этот пост за последние три года и начали писать глючный код.
— Кодзиро

16
Имейте в виду, что первый пример дает вам строку, а не дату или время.
— Гак

1
@kojiro сообщение в блоге вы связаны с может быть более явным , что на Unix к файлу ctimeобновляется всякий раз , когда mtimeделает (так как mtimeэто «метаданные»), и поэтому , ctimeкак правило , всегда равна или больше , чемmtime . ctimeТаким образом, трактовать время как «созданное» не имеет никакого смысла. -1!
— Марк Амери

Ваша первая опция возвращает одинаковые результаты как для создания файла, так и для последней модификации! Last modified: Fri Jan 31 11:08:13 2020и Created: Fri Jan 31 11:08:13 2020на Linux Ubuntu 16.04!
— Ферид Алиджани

Я обнаружил, что time.ctime(os.path.getmtime(file))возвращает 2 типа строк, в зависимости от того, был ли файл изменен системой или пользователем. Если она была изменена системой, строка будет иметь 2 пробела между месяцем и днем. Я не знаю почему
— Маттео Антолини

376

Лучшая функция для этого - os.path.getmtime () . Внутренне это просто использует os.stat(filename).st_mtime.

Модуль datetime - это лучшая манипуляция с временными метками, поэтому вы можете получить дату модификации в виде datetimeобъекта:

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

Пример использования:

>>> 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
Этот ответ также немного неправильный. getmtimeэто самая близкая вещь, доступная в Unix (где получение дат создания невозможно), но это определенно не лучшая функция для использования в Windows, где время ctimeсоздания.
— Марк Амери

3
@MarkAmery - Этот ответ четко обозначен как время модификации.
— ArtOfWarfare

47

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

edit: в более новом коде вы, вероятно, должны использовать os.path.getmtime () (спасибо Christian Oudard),
но обратите внимание, что он возвращает значение с плавающей запятой time_t с долями секунды (если ваша ОС поддерживает это)


44
os.path.getmtime () создан для этого и проще.
— Кристиан Удард

5
Предложение «в новом коде» здесь немного вводит в заблуждение. os.path.getmtime()существует с Python 1.5.2 (см. старые документы ), выпущенного до того, как я потерял большую часть своих молочных зубов, и почти за десять лет до того, как вы написали оригинальную версию этого ответа.
— Марк Амери

39

Есть два метода для получения времени мода, os.path.getmtime () или os.stat (), но ctime не является надежной кроссплатформенной (см. Ниже).

os.path.getmtime ()

getmtime ( path )
Возвращает время последней модификации пути. Возвращаемое значение - это число, указывающее количество секунд с начала эпохи (см. Модуль времени). Поднимите os.error, если файл не существует или недоступен. Новое в версии 1.5.2. Изменено в версии 2.3: если os.stat_float_times () возвращает True, результатом является число с плавающей запятой.

os.stat ()

stat ( путь )
Выполнить системный вызов stat () по заданному пути. Возвращаемое значение - это объект, атрибуты которого соответствуют членам структуры статистики, а именно: st_mode (защитные биты), st_ino (номер индекса), st_dev (устройство), st_nlink (количество жестких ссылок), st_uid (идентификатор пользователя владельца ), st_gid (идентификатор группы владельца), st_size (размер файла, в байтах), st_atime (время самого последнего доступа), st_mtime (время самой последней модификации контента), st_ctime (зависит от платформы; время самого последнего изменения метаданных в Unix или время создания в Windows) :

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

В приведенном выше примере вы должны использовать statinfo.st_mtime или statinfo.st_ctime, чтобы получить mtime и ctime соответственно.


13

В Python 3.4 и выше вы можете использовать объектно-ориентированный интерфейс модуля pathlib, который включает в себя оболочки для большей части модуля os. Вот пример получения статистики по файлу.

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

Для получения дополнительной информации о том os.stat_result, что содержится, обратитесь к документации . За время модификации вы хотите 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)

Если вам нужно время создания в Windows или самое последнее изменение метаданных в Unix, вы должны использовать fname.stat().st_ctime:

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

Эта статья содержит более полезную информацию и примеры для модуля pathlib.


11

os.statвозвращает именованный кортеж st_mtimeи st_ctimeатрибуты. Время модификации st_mtimeна обеих платформах; к сожалению, в Windows это ctimeозначает «время создания», а в POSIX - «время изменения». Я не знаю ни одного способа получить время создания на платформах POSIX.


Подробнее о тегированных кортежах: stackoverflow.com/questions/2970608/… Они работают как кортежи, но попробуйте dir(..)один. Напримерdir(os.stat(os.listdir('.')[0]))
— Евгений Сергеев

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

печать

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: То же, что и в других ответах, это не даст вам время создания файла в Windows (что, опять же, даже не упоминается в ответе).
— ntninja

@ntninja ты уверен в этом? Я использую только Windows, и это абсолютно работает. Я написал этот сценарий в начале 2015 года. Я считаю, что он был более понятным, понятным, полным и понятным, чем другие здесь. (что я решил найти здесь вместо моих старых сценариев, только если было что-то новое. Нет ... это путь)
— Лужа

О, я хотел сказать «… это не даст вам время создания файла, если вы не в Windows». Сожалею! Факт остается фактом, что этот ответ не является переносимым и не упоминает этот факт. (Пример вывода в Linux: pastebin.com/50r5vGBE )
— ntninja

@ntninja ты собираешься рассказать всем остальным тогда?
— лужа

Я уже оставил здесь несколько других комментариев, и я скоро выложу ответ, который работает и на (недавней) Linux. Но на самом деле, единственное, что не так в вашем посте, - это то, что ответ только для Windows не упоминает этот факт. В вопросе OP даже специально задавалось вопрос о совместимости Windows и Linux. Поэтому я думаю, что было бы очень полезно, если бы вы добавили эту «деталь» где-то вверху, чтобы люди не вводили в заблуждение, думая, что ctime - это то, что они ищут, ориентируясь на несколько платформ.
— ntninja

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

-1: как уже упоминалось в другом месте, это не даст вам время создания файла, если вы не находитесь в Windows (о которой даже не упоминается ответ!).
— ntninja

0

Если следующие символические ссылки не важны, вы также можете использовать os.lstatвстроенную функцию.

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

Это даст время последнего чтения (по крайней мере, в Unix), что определенно не то, о чем просили.
— Марк Амери

0

Возможно, стоит взглянуть на crtimeбиблиотеку, которая реализует кроссплатформенный доступ ко времени создания файла.

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
Я настоятельно рекомендую это сделать: он использует debugfsLinux, который по определению нестабилен, требует корневого доступа на высшем уровне для всего и почти во всех аспектах - одна из тех вещей, о которых ваша мама всегда предупреждала. (Но да, это, вероятно, работает, если вы действительно отчаялись и оказались настоящим суперпользователем в системе без безопасной загрузки…)
— ntninja

@ntninja Я бы, вероятно, никогда не использовал бы в производстве, но это может быть полезно для "домашнего сценария".
— Дельган

-2

os.statдействительно включает время создания. Просто нет определения st_anything для элемента, os.stat()который содержит время.

Итак, попробуйте это:

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

Сравните это с датой создания файла в ls -lah.

Они должны быть одинаковыми.


6
Неправильно! os.stat ('feedparser.py') [8] ссылается на st_mtime, а не на время создания. Пожалуйста, обратитесь к документации: docs.python.org/library/os.html#os.stat
— millerdev

4
Пожалуйста, используйте .st_ctime вместо некрасивых чисел [8].
— Геттли

-3

Я смог получить время создания в posix, запустив системную команду stat и проанализировав вывод.

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

Запуск stat вне python из терминала (OS X) вернул:

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

... где четвертой датой является время создания файла (а не время изменения ctime, как отмечалось в других комментариях).


13
-1: анализ выходных данных, предназначенных для людей, по команде оболочки - очень плохая идея. И эта команда даже не является кросс-совместимой.
— МестреЛион
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.