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

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

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


person Mark Biek    schedule 25.10.2008    source источник
comment
Вы не можете получить время создания файла кроссплатформенным способом. См. docs.python.org/library/os.path.html. # os.path.getctime   -  person Glyph    schedule 19.07.2010
comment
Имейте в виду, что принятый ответ больше не рекомендуется, используйте pathlib вместо os, см. Ответ @ StevenC.Howell. Возможно, можно было бы даже изменить принятый ответ на pathlib ответ?   -  person questionto42    schedule 30.11.2020


Ответы (13)


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

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

person Steven C. Howell    schedule 17.10.2018

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

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

  • В Windows ctime файла (задокументировано по адресу https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx) хранит дату его создания. Вы можете получить доступ к этому в Python через os.path.getctime() или < атрибут href = "https://docs.python.org/3/library/os.html#os.stat_result.st_ctime" rel = "noreferrer"> _ 5_ результата вызова _ 6_. Это не работает в Unix, где ctime - это последний раз, когда атрибуты файла или изменялись.
  • На Mac, а также в некоторых других ОС на базе Unix можно использовать _ 8_ атрибут результата вызова 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
person Mark Amery    schedule 14.09.2016
comment
Я приложил все усилия, чтобы собрать это вместе (и потратил несколько часов на изучение этого процесса), и я уверен, что это по крайней мере более правильное, чем ответы, которые были здесь ранее, но это действительно сложная тема, и я буду признателен за любые исправления, пояснения или другие предложения, которые могут предложить люди. В частности, я хотел бы создать способ доступа к этим данным на ext4 дисках под Linux, и я хотел бы узнать, что происходит, когда Linux читает файлы, написанные Windows, или наоборот, учитывая, что они используют st_ctime по-разному. - person Mark Amery; 15.09.2016
comment
Честно говоря, время создания файла обычно бесполезно. Когда вы открываете существующий файл для записи в режиме "w", он не заменяет его, он просто открывает существующий файл и обрезает его. Несмотря на то, что содержимое файла совершенно не связано с тем, что он имел при создании, вам все равно скажут, что файл был создан задолго до текущей версии. И наоборот, редакторы, которые используют атомарную замену при сохранении (исходный файл заменяется новым временным файлом в процессе), будут отображать более позднюю дату создания, даже если вы просто удалили один символ. Используйте время модификации, не тратите время на создание. - person ShadowRanger; 17.10.2016
comment
Спустя много лет я наконец нашел применение времени создания файлов! Я пишу код для проверки соглашения об именах файлов в определенных каталогах, поэтому в первую очередь я хочу рассмотреть файлы, которые были впервые названы после того, как соглашение было установлено. Замена всего содержимого (mtime) не имеет значения: если оно уже было там, значит, оно унаследовано. - person Steve Jessop; 03.12.2016
comment
Привет Марк. Предлагаю упрощение. В Linux возвращение stat.st_ctime равно более уместно, потому что во многих случаях время последнего изменения метаданных может быть временем создания (по крайней мере ctime ближе к реальному времени создания, чем mtime). Поэтому вы можете просто заменить свой фрагмент на stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime. Что вы думаете? Ваше здоровье - person oHo; 07.08.2017
comment
@olibre по крайней мере ctime ближе к реальному времени создания, чем mtime - нет, это не так; это то, что я видел несколько раз, но это абсолютно неверно. Если вы вручную не испортили значения в своем индексном дескрипторе, ctime всегда должно быть равно или позже, чем mtime, потому что изменение mtime вызывает изменение ctime (поскольку mtime сам считается метаданными). См. stackoverflow.com/a/39521489/1709587, где я привожу пример кода, чтобы проиллюстрировать это. - person Mark Amery; 09.08.2017
comment
Всякий раз, когда появляется st_ctime, нам нужны эти уродливые заявления об отказе от ответственности о различном значении в Windows, и это делает уродливый код, даже если ctime редко используется. Я хотел бы изменить реализацию os.stat в Windows для поддержки st_birthtime в дополнение к st_ctime, но отказаться от использования st_ctime в качестве времени создания. Переменная среды позволит использовать st_ctime в качестве времени изменения (поддерживается NTFS; нам пришлось бы изменить запросы, используемые для реализации os.stat), что впоследствии будет сделано по умолчанию в следующей версии. - person Eryk Sun; 10.07.2018
comment
Если файлы являются изображениями, вы также можете попытаться получить дату съемки, используя PIL: `from PIL import Image def get_date_taken (path): try: return Image.open (path) ._ getexif () [36867] except: return os .path.getmtime (путь) ` - person Fernando Wittmann; 23.11.2018
comment
Обратите внимание, что утверждение «Хотя некоторые файловые системы, обычно используемые в Linux, действительно хранят даты создания […], ядро ​​Linux не предлагает возможности доступа к ним», с момента выхода Linux 4.11) уже не соответствует действительности: системный вызов statx делает разрешить запросы btime, если они доступны для данного файла. (Однако это не используется / не отображается даже в Python 3.8.) - person ntninja; 05.01.2020

У вас есть несколько вариантов. Например, вы можете использовать os.path.getmtime и _ 2_ функции:

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, а скорее ко времени последнего изменения данных inode. (спасибо kojiro за то, что он разъяснил этот факт в комментариях, предоставив ссылку на интересный пост в блоге)

person Bryan Oakley    schedule 25.10.2008
comment
На всякий случай, если кто-то пропустит комментарий @ Glyph к вопросу, ctime не означает время создания в системах POSIX. Интересно, сколько людей просмотрели этот пост за последние три года и продолжили писать ошибочный код. - person kojiro; 08.11.2011
comment
Имейте в виду, что первый пример дает вам строку, а не дату, время или число. - person gak; 12.07.2013
comment
@kojiro сообщение в блоге, на которое вы ссылаетесь, может быть более явным, что в Unix файл ctime обновляется всякий раз, когда это делает mtime (поскольку mtime является метаданными), и поэтому ctime обычно всегда равно или опережает < / i> mtime. Таким образом, трактовка ctime как созданного времени вообще не имеет смысла. -1! - person Mark Amery; 12.09.2016
comment
Ваш первый вариант возвращает одинаковые результаты как для создания файла, так и для последнего изменения! Last modified: Fri Jan 31 11:08:13 2020 и Created: Fri Jan 31 11:08:13 2020 в Linux Ubuntu 16.04! - person Färid Alijani; 31.01.2020
comment
Я обнаружил, что time.ctime(os.path.getmtime(file)) возвращает 2 типа строк, в зависимости от того, был ли файл изменен системой или пользователем. Если он был изменен системой, в строке будет два пробела между месяцем и днем. Я не знаю почему - person Matteo Antolini; 10.04.2020

Лучшая функция для этого - 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)
person Christian Oudard    schedule 06.10.2009
comment
Этот ответ тоже немного неверен. getmtime - это ближайшая функция, доступная в Unix (где получение дат создания невозможно), но определенно не лучшая функция для использования в Windows, где ctime - время создания. - person Mark Amery; 12.09.2016
comment
@MarkAmery - этот ответ явно помечен как просто о времени модификации. - person ArtOfWarfare; 19.01.2017

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

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

person Martin Beckett    schedule 25.10.2008
comment
os.path.getmtime () создан для этого и проще. - person Christian Oudard; 06.10.2009
comment
Предложение в новом коде здесь немного вводит в заблуждение. os.path.getmtime() существует с Python 1.5.2 (см. старые документы), выпущенный до того, как я потерял большую часть молочных зубов, и почти за десять лет до того, как вы написали исходную версию этого ответа. - person Mark Amery; 12.09.2016

Есть два метода получения времени модификации: 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 (path)
Выполнить системный вызов stat () для заданного пути. Возвращаемое значение - это объект, атрибуты которого соответствуют членам структуры stat, а именно: st_mode (биты защиты), st_ino (номер inode), 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 соответственно.

person Jay    schedule 25.10.2008

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
person Puddle    schedule 03.12.2018
comment
@ntninja, ты в этом уверен? Я использую только Windows, и это абсолютно работает. Я написал этот сценарий в начале 2015 года. Я считаю, что он был более ясным, точным, полным и самоочевидным, чем другие здесь. (который я решил посмотреть здесь вместо моих старых скриптов на случай, если будет что-то новое. нет ... это способ) - person Puddle; 09.01.2020
comment
О, я хотел сказать: «… это не даст вам времени на создание файла, если вы не используете Windows». Извините! Факт остается фактом: этот ответ непереносим и не упоминает об этом факте. (Пример вывода в Linux: pastebin.com/50r5vGBE) - person ntninja; 09.01.2020
comment
@ntninja, тогда ты расскажешь всем остальным? - person Puddle; 11.01.2020
comment
Я уже оставил здесь несколько других комментариев, и вскоре я опубликую ответ, который работает и на (недавнем) Linux. Но на самом деле единственное, что неправильно в вашем сообщении, это то, что это ответ только для Windows, в котором этот факт не упоминается. В вопросе OP даже специально попросил решение, совместимое с Windows и Linux. Таким образом, я думаю, было бы очень полезно, если бы вы добавили эту «деталь» где-нибудь вверху, чтобы люди не заблуждались, думая, что ctime - это то, что они ищут, когда ориентируются на несколько платформ. - person ntninja; 11.01.2020

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

person mithrandi    schedule 25.10.2008
comment
Подробнее о тегированных кортежах: http://stackoverflow.com/questions/2970608/what-are-named-tuples-in-python Они работают как кортежи, но попробуйте dir(..) на одном. Например. dir(os.stat(os.listdir('.')[0])) - person Evgeni Sergeev; 16.10.2013

Возможно, стоит взглянуть на библиотеку 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
person Community    schedule 27.05.2019
comment
Я настоятельно не рекомендую этого: он использует debugfs в Linux, который по определению нестабилен, требует корневого доступа верхнего уровня для всего и почти во всех аспектах имеет тенденцию быть одной из тех вещей, о которых ваша мать всегда предупреждала вас. (Но да, это, вероятно, сработает, если вы действительно в отчаянии и оказались настоящим суперпользователем в системе без безопасной загрузки…) - person ntninja; 08.01.2020
comment
@ntninja Я бы, вероятно, никогда не стал бы использовать в продакшене, но он может быть полезен для домашнего написания сценариев. - person Delgan; 08.01.2020
comment
Да, согласен. Я создал это для действительно отчаявшихся. - person PascalVKooten; 25.02.2021

Если переход по символическим ссылкам не важен, вы также можете использовать встроенный 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
person Muhammad Lukman Low    schedule 11.02.2015
comment
Это даст время последнего чтения (по крайней мере, в Unix), что определенно не соответствует запросу. - person Mark Amery; 12.09.2016

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

Так что попробуйте это:

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

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

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

person Community    schedule 14.12.2008
comment
Неправильный! os.stat ('feedparser.py') [8] относится к st_mtime, а не к времени создания. См. Документацию: docs.python.org/library/os.html# os.stat - person millerdev; 11.06.2011
comment
Пожалуйста, используйте .st_ctime вместо уродливых чисел [8]. - person guettli; 04.12.2012

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

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

Выполнение статистики вне 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

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

person kmarchand    schedule 29.08.2013
comment
-1: Анализ вывода, предназначенного для людей, из команды оболочки - очень плохая идея. И эта команда даже не является кросс-совместимой. - person MestreLion; 05.11.2013

person    schedule
comment
-1: Как упоминалось в другом месте, это не даст вам времени создания файла, если вы не работаете в Windows (о чем в ответе даже не упоминается!). - person ntninja; 08.01.2020