获取文件修改时间到纳秒精度

时间:2013-10-14 00:24:57

标签: python linux datetime filesystems precision

我需要为遍历文件系统树的Python 2程序中的每个文件获取完整的纳秒精度修改时间戳。我想在Python本身中这样做,因为为每个文件生成一个新的子进程会很慢。

通过查看st_mtime_nsec结果的stat字段,从Linux上的C库you can get nanosecond-precision timestamps开始。例如:

#include <sys/stat.h>
#include <stdio.h>
int main() {
    struct stat stat_result;
    if(!lstat("/", &stat_result)) {
        printf("mtime = %lu.%lu\n", stat_result.st_mtim.tv_sec, stat_result.st_mtim.tv_nsec);
    } else {
        printf("error\n");
        return 1;
    }
}

打印mtime = 1380667414.213703287/位于ext4文件系统上,支持纳秒时间戳,时钟为UTC。)

同样,date --rfc-3339=ns --reference=/打印2013-10-01 22:43:34.213703287+00:00

Python(2.7.3)的os.path.getmtime(filename)os.lstat(filename).st_mtime将mtime视为float。但结果是错误的:

In [1]: import os
In [2]: os.path.getmtime('/') % 1
Out[2]: 0.21370339393615723
In [3]: os.lstat('/').st_mtime % 1
Out[3]: 0.21370339393615723

- 前6位数字是正确的,可能是由于浮点错误。

3 个答案:

答案 0 :(得分:6)

os.stat('/').st_mtime是一个浮点对象,浮点数的精度对于纳秒时间戳来说太低了,

  

Python的浮点数的基础类型是IEEE 754双精度,即   仅适用于大约16位小数。前面有十位数字   小数点,为亚秒分辨率留下六个,即   三个不足以保留POSIX所需的范围   纳秒分辨率时间戳。通过:This Week in Python Stupidity: os.stat, os.utime and Sub-Second Timestamps

如果你可以使用Python 3,那么有一个名为st_mtime_ns的新属性,它是以纳秒为单位的st_mtime。试试吧。

>>> os.stat('.').st_mtime
1381571932.044594
>>> os.stat('.').st_mtime_ns
1381571932044593972

参考文献:

PEP 410 -- Use decimal.Decimal type for timestamps

os.stat(): add new fields to get timestamps as Decimal objects with nanosecond resolution

add st_*time_ns fields to os.stat(), add ns keyword to os.utime(), os.utimens() expects a number of nanoseconds

答案 1 :(得分:3)

或者你可以使用与Python 2一起使用的cffi库和下面的代码(在LInux上测试):

from __future__ import print_function

from cffi import FFI

ffi = FFI()
ffi.cdef("""
typedef long long time_t;

typedef struct timespec {
    time_t   tv_sec;
    long     tv_nsec;
    ...;
};

typedef struct stat {
    struct timespec st_mtim;
    ...;
};

int lstat(const char *path, struct stat *buf);
""")

C = ffi.verify()

result = ffi.new("struct stat *")
p = C.lstat("foo.txt", result)
print("mtime = {0:d}.{1:09d}".format(result.st_mtim.tv_sec, result.st_mtim.tv_nsec))

这与您的问题中的C程序行为完全相同。 这会产生输出:

$ ./test.py
mtime = 1381711568.315075616

与C程序具有相同的精度:

$ gcc test.c -o test
$ ./test
mtime = 1381711568.315075616

答案 2 :(得分:1)

我打算像glasslion一样说 - Python将st_mtime转换为浮点数,这会失去有效数字。

一种替代方法是使用“ctypes”模块或cython直接访问C库,这应该在纳秒字段中返回一个很好的无符号长整数,(不能给你一个例子,因为你没有给出有关您的操作系统的任何信息。)