7

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

在 Linux 上的 C 库中,您可以通过查看结果字段来获得纳秒级精度的时间戳。例如:st_mtime_nsecstat

#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_mtimemtime 作为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 位数字是正确的,可能是由于浮点错误。

4

3 回答 3

10

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

Python 的浮点基础类型是 IEEE 754 双精度型,仅适用于大约 16 位十进制数字。小数点前有十位,亚秒级分辨率剩下六位,比保留 POSIX 纳秒分辨率时间戳所需的范围少三。通过:本周 Python 愚蠢:os.stat、os.utime 和亚秒时间戳

如果您可以使用 Python 3,则有一个名为 的新属性st_mtime_ns,即 st_mtime 以纳秒为单位。尝试一下。

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

参考:

PEP 410 -- 使用十进制。十进制类型的时间戳

os.stat():添加新字段以获取时间戳作为具有纳秒分辨率的十进制对象

在 os.stat() 中添加 st_*time_ns 字段,在 os 中添加 ns 关键字。utime(),操作系统。utimens () 需要几纳秒

于 2013-10-14T02:13:55.163 回答
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
于 2013-10-14T04:11:05.080 回答
1

我想说的和 glasslion 一样——Python 将 st_mtime 转换为浮点数,它会丢失有效数字。

一种替代方法是使用“ctypes”模块或 cython 直接访问 C 库,它应该在纳秒字段中返回一个不错的 unsigned long (不能给你一个例子,因为你没有提供任何关于您的操作系统)。

于 2013-10-14T02:40:43.690 回答