touch是一个Unix实用程序,它将文件的修改和访问时间设置为一天中的当前时间。如果该文件不存在,则使用默认权限创建该文件。

如何将其实现为Python函数?尽量跨平台和完整。

(目前谷歌的“python触摸文件”的结果不是很好,但指向os.utime。)


当前回答

我有一个用于备份的程序:https://stromberg.dnsalias.org/~strombrg/backshift/

我使用vmprof对它进行了分析,发现到目前为止,触摸是最耗时的部分。

所以我研究了快速接触文件的方法。

我发现在CPython 3.11上,这是最快的:

def touch3(filename, flags=os.O_CREAT | os.O_RDWR):                                                                                  
    """Touch a file using os.open+os.close - fastest on CPython 3.11."""                                                             
    os.close(os.open(filename, flags, 0o644))    

                                                                                

在Pypy3 7.3.9上,这是最快的:

def touch1(filename):                                                                                                                
    """Touch a file using pathlib - fastest on pypy3, and fastest overall."""                                                        
    Path(filename).touch()                                                                                                           

在这两者中,pypy3的最佳性能仅略快于cpython的最佳性能。

我可能有一天会创建一个关于这个的网页,但现在我所拥有的只是一个Subversion repo: https://stromberg.dnsalias.org/svn/touch/trunk 它包括我尝试过的4种触摸方式。

其他回答

下面是一些使用ctypes的代码(仅在Linux上测试):

from ctypes import *
libc = CDLL("libc.so.6")

#  struct timespec {
#             time_t tv_sec;        /* seconds */
#             long   tv_nsec;       /* nanoseconds */
#         };
# int futimens(int fd, const struct timespec times[2]);

class c_timespec(Structure):
    _fields_ = [('tv_sec', c_long), ('tv_nsec', c_long)]

class c_utimbuf(Structure):
    _fields_ = [('atime', c_timespec), ('mtime', c_timespec)]

utimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf))
futimens = CFUNCTYPE(c_int, c_char_p, POINTER(c_utimbuf)) 

# from /usr/include/i386-linux-gnu/bits/stat.h
UTIME_NOW  = ((1l << 30) - 1l)
UTIME_OMIT = ((1l << 30) - 2l)
now  = c_timespec(0,UTIME_NOW)
omit = c_timespec(0,UTIME_OMIT)

# wrappers
def update_atime(fileno):
        assert(isinstance(fileno, int))
        libc.futimens(fileno, byref(c_utimbuf(now, omit)))
def update_mtime(fileno):
        assert(isinstance(fileno, int))
        libc.futimens(fileno, byref(c_utimbuf(omit, now)))

# usage example:
#
# f = open("/tmp/test")
# update_mtime(f.fileno())

简单的:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)

打开确保那里有一个文件 utime确保时间戳被更新

从理论上讲,可能有人会在打开文件后删除该文件,导致utime引发异常。但可以说这没什么,因为坏事确实发生了。

对于更低级的解决方案,可以使用

os.close(os.open("file.txt", os.O_CREAT))

还有一个用于触摸的python模块

>>> from touch import touch
>>> touch(file_name)

你可以用pip install touch安装它

with open(file_name,'a') as f: 
    pass