我如何在Python脚本中获取Excel文件的创建日期?
问题的出现的原因是用户想要在Python脚本中获取Excel文件的创建日期。解决方法是使用os.path.getmtime()函数来获取最后修改时间,然后使用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) print(repr(d))
这段代码将返回Excel文件的修改日期,示例输出为"2009-10-06 10:50:01"和"datetime.datetime(2009, 10, 6, 10, 50, 1)"。
文章中还提到了一个错误,即在Unix系统上,使用getmtime函数可以获取最近的修改时间,但在Windows系统上,ctime函数可以获取到创建时间。此外,还建议在返回datetime对象时使用datetime.timezone.utc参数来指定时区,以避免产生时区解释错误的问题。
问题的出现原因:用户想要在Python脚本中获取Excel文件的创建日期。
解决方法:
1. 使用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)))
2. 使用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数据最后一次更改的时间。
还有一些评论指出,ctime并不代表POSIX系统上的创建时间,而是最后更改时间。因此,在Unix系统中,将ctime视为“创建”时间是毫无意义的。
另外,第一个选项返回的是字符串,而不是datetime或数字。
此外,还有一些评论提到,time.ctime(os.path.getmtime(file))返回两种不同类型的字符串,取决于文件是由系统修改还是由用户修改。如果文件是由系统修改的,则字符串中的月份和日期之间会有两个空格,原因不明。
如何在Python脚本中获取Excel文件的创建日期?
获取跨平台的某种修改日期很容易-只需调用`os.path.getmtime(path)`,就可以获得`path`路径下的文件上次修改的Unix时间戳。
然而,获取文件的创建日期则更加棘手且依赖于不同的操作系统,即使在三个主要的操作系统之间也存在差异:
- 在Windows上,文件的`ctime`(文档记录在https://msdn.microsoft.com/en-us/library/14h5k7ff.aspx)存储了其创建日期。可以通过在Python中使用`os.path.getctime()`或调用`os.stat()`并访问返回结果的`st_ctime`属性来获取。
- 在Mac以及其他一些基于Unix的操作系统上,可以使用调用`os.stat()`的结果的`st_birthtime`属性。
- 在Linux上,目前是不可能的,至少不写一个Python的C扩展。尽管一些常用于Linux的文件系统(例如ext4)存储了创建日期(在`st_crtime`中),Linux内核却没有提供访问它们的方法。从最新的内核版本开始,从C语言的`stat()`调用返回的结构体中也不包含任何创建日期字段。如果你使用的是ext4文件系统,数据实际上是附加到文件系统中的inode上的,但没有方便的方式来访问它。
在Linux上,最好的方式是访问文件的`mtime`,可以通过使用`os.path.getmtime()`或者`os.stat()`结果的`st_mtime`属性来获取。这将给出文件内容上次修改的时间,对于某些用例可能足够了。
综合起来,跨平台的代码应该如下所示:
import os import platform def creation_date(path_to_file): 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: return stat.st_mtime
文件创建时间通常是相当无用的。当你以写入模式`"w"`打开现有文件时,它并不是替换文件,而是打开现有文件并截断它。即使文件内容与创建时完全无关,你仍然会被告知文件在当前版本之前"创建"。相反,使用原子替换保存的编辑器(原始文件被新的工作中临时文件替换)将显示更近期的创建日期,即使只删除一个字符。使用修改时间,不要去寻找创建时间。
多年以后,我终于找到了使用文件创建时间的用途!我正在编写代码来检查某些目录中的文件命名约定,所以首先我希望考虑那些在约定实施后首次命名的文件。完全替换(mtime)的文件内容是无关紧要的:如果已经存在,则它是老资格的。
我提出了一个简化。在Linux上,返回`stat.st_ctime`更相关,因为在许多情况下,最后的元数据更改时间可能是创建时间(至少`ctime`比`mtime`更接近真正的创建时间)。因此,你可以简单地将代码段替换为`stat = os.stat(path_to_file); try: return stat.st_birthtime; except AttributeError: return stat.st_ctime`。你觉得怎么样?谢谢。
“至少ctime比mtime更接近真正的创建时间”-不,它不是。这是我见过几次的陈述,但它完全错误。除非你手动修改了inode中的值,否则`ctime`应始终等于或晚于`mtime`,因为`mtime`的更改会导致`ctime`的更改(因为`mtime`本身被认为是“元数据”)。请参见https://stackoverflow.com/a/39521489/1709587,我在其中提供了一些示例代码来说明这一点。
每当`st_ctime`出现时,我们需要这些关于Windows中不同含义的丑陋警告,即使很少使用`ctime`也会导致丑陋的代码。我希望更改`os.stat`在Windows上的实现,以支持`st_birthtime`以及`st_ctime`,但不建议将`st_ctime`用作“创建时间”。通过环境变量,可以使用`st_ctime`作为更改时间(NTFS支持;我们必须修改用于实现`os.stat`的查询),这将在下一个版本中成为默认选项。
如果文件是图像,你还可以尝试使用PIL库获取拍摄日期:
from PIL import Image def get_date_taken(path): try: return Image.open(path)._getexif()[36867] except: return os.path.getmtime(path)
需要注意的是,这里的陈述“尽管一些常用于Linux的文件系统存储了创建日期,但Linux内核却没有提供访问它们的方法”已经不再正确,自Linux 4.11以来,`statx`系统调用允许查询给定文件的`btime`(如果可用)。但是,即使在Python3.8中,这个特性也没有被使用/暴露出来。
在Linux中,可以使用类似`int(subprocess.check_output(["stat", "--printf", "%W", path_to_file]))`的方式来获取创建/出生日期。