Mec*_*ail 4 python linux filesystems precision datetime
我需要为遍历文件系统树的Python 2程序中的每个文件获取完整的纳秒精度修改时间戳.我想在Python本身中这样做,因为为每个文件生成一个新的子进程会很慢.
从Linux上的C库,您可以通过查看结果st_mtime_nsec字段来获得纳秒级精度时间戳stat.例如:
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
打印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
Run Code Online (Sandbox Code Playgroud)
- 前6位数字是正确的,可能是由于浮点错误.
os.stat('/').st_mtime 是一个浮点对象,浮点数的精度对于纳秒的时间戳来说太低了,
Python的浮点数的基础类型是IEEE 754双精度,它只适用于大约16位十进制数字.在小数点前十位数,为亚秒级分辨率留下六位数,这是保留POSIX纳秒分辨率时间戳所需范围的三倍.via:本周Python愚蠢:os.stat,os.utime和Sub-Second Timestamps
如果你可以使用Python 3,那么就会有一个名为st_mtime_nsst_mtime 的新属性,以纳秒为单位.试试吧.
>>> os.stat('.').st_mtime
1381571932.044594
>>> os.stat('.').st_mtime_ns
1381571932044593972
Run Code Online (Sandbox Code Playgroud)
参考文献:
PEP 410 - 使用decimal.Decimal类型作为时间戳
os.stat():添加新字段以将时间戳作为具有纳秒分辨率的Decimal对象
将st_*time_ns字段添加到os.stat(),将ns关键字添加到os.utime(),os.utimens()需要几纳秒
或者,您可以使用cffi库,该库与 Python 2 一起使用,代码如下(在 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))
Run Code Online (Sandbox Code Playgroud)
这与您问题中的 C 程序的行为相同。这会产生输出:
$ ./test.py
mtime = 1381711568.315075616
Run Code Online (Sandbox Code Playgroud)
其精度与 C 程序相同:
$ gcc test.c -o test
$ ./test
mtime = 1381711568.315075616
Run Code Online (Sandbox Code Playgroud)