使用 Python 实现触摸?

2025-03-04 08:25:00
admin
原创
69
摘要:问题描述:touch是一个 Unix 实用程序,用于将文件的修改和访问时间设置为当前时间。如果文件不存在,则使用默认权限创建该文件。您将如何将其实现为 Python 函数?尝试跨平台且完整。(目前 Google 搜索“python touch file”的搜索结果并不理想,但指向os.utime。)解决方案 ...

问题描述:

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

您将如何将其实现为 Python 函数?尝试跨平台且完整。

(目前 Google 搜索“python touch file”的搜索结果并不理想,但指向os.utime。)


解决方案 1:

看起来这是 Python 3.4 中的新功能 - pathlib

from pathlib import Path

Path('path/to/file.txt').touch()

这将file.txt在路径上创建一个。

--

路径.触摸(模式=0o777,exist_ok=True)

在给定路径下创建一个文件。如果给出了模式,则将其与进程的 umask 值相结合以确定文件模式和访问标志。如果文件已存在,则如果 exist_ok 为真(并且其修改时间更新为当前时间),则该函数成功,否则会引发 FileExistsError。

解决方案 2:

与其他解决方案相比,此解决方案尽量避免竞争。(该with关键字是 Python 2.5 中的新增功能。)

import os
def touch(fname, times=None):
    with open(fname, 'a'):
        os.utime(fname, times)

大致相当于这个。

import os
def touch(fname, times=None):
    fhandle = open(fname, 'a')
    try:
        os.utime(fname, times)
    finally:
        fhandle.close()

现在,要真正实现无竞争,您需要使用并更改打开文件句柄的时间戳,而不是打开文件然后更改文件名(可能已重命名)上的时间戳。不幸的是,Python 似乎没有提供不经过或类似futimes操作即可调用的方法...futimes`ctypes`


编辑

正如Nate Parsons所指出的,Python 3.3 将为诸如 之类的函数添加 指定文件描述符(当 时os.supports_fd)的功能os.utime,这将使用futimessyscall 而不是utimes底层的 syscall。换句话说:

import os
def touch(fname, mode=0o666, dir_fd=None, **kwargs):
    flags = os.O_CREAT | os.O_APPEND
    with os.fdopen(os.open(fname, flags=flags, mode=mode, dir_fd=dir_fd)) as f:
        os.utime(f.fileno() if os.utime in os.supports_fd else fname,
            dir_fd=None if os.supports_fd else dir_fd, **kwargs)

解决方案 3:

def touch(fname):
    if os.path.exists(fname):
        os.utime(fname, None)
    else:
        open(fname, 'a').close()

解决方案 4:

为什么不尝试一下呢?:

import os

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

我相信这可以消除任何重要的竞争条件。如果文件不存在,则会引发异常。

这里唯一可能的竞争条件是文件是在调用 open() 之前但在 os.utime() 之后创建的。但这并不重要,因为在这种情况下,修改时间将如预期的那样,因为它一定是在调用 touch() 期间发生的。

解决方案 5:

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

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

为了进行比较,GNU touch 使用

O_WRONLY | O_CREAT | O_NONBLOCK | O_NOCTTY

其中 为modeMODE_RW_UGO0o666

解决方案 6:

with此答案与自关键字发布以来的 Python-2.5 的所有版本兼容。

1. 如果不存在则创建文件 + 设置当前时间

(与命令完全相同touch

import os

fname = 'directory/filename.txt'
with open(fname, 'a'):     # Create file if does not exist
    os.utime(fname, None)  # Set access/modified times to now
                           # May raise OSError if file does not exist

更加强大的版本:

import os

with open(fname, 'a'):
  try:                     # Whatever if file was already existing
    os.utime(fname, None)  # => Set current time anyway
  except OSError:
    pass  # File deleted between open() and os.utime() calls

2. 如果不存在则创建文件

(不更新时间)

with open(fname, 'a'):  # Create file if does not exist
    pass

3. 仅更新文件访问/修改时间

(如果不存在则不创建文件)

import os

try:
    os.utime(fname, None)  # Set access/modified times to now
except OSError:
    pass  # File does not exist (or no permission)

使用os.path.exists()不会简化代码:

from __future__ import (absolute_import, division, print_function)
import os

if os.path.exists(fname):
  try:
    os.utime(fname, None)  # Set access/modified times to now
  except OSError:
    pass  # File deleted between exists() and utime() calls
          # (or no permission)

奖励:目录中所有文件的更新时间

from __future__ import (absolute_import, division, print_function)
import os

number_of_files = 0

#   Current directory which is "walked through"
#   |     Directories in root
#   |     |  Files in root       Working directory
#   |     |  |                     |
for root, _, filenames in os.walk('.'):
  for fname in filenames:
    pathname = os.path.join(root, fname)
    try:
      os.utime(pathname, None)  # Set access/modified times to now
      number_of_files += 1
    except OSError as why:
      print('Cannot change time of %r because %r', pathname, why)

print('Changed time of %i files', number_of_files)

解决方案 7:

以下是一些使用 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())

解决方案 8:

简单来说:

def touch(fname):
    open(fname, 'a').close()
    os.utime(fname, None)
  • 确保open那里有一个文件

  • 确保utime时间戳得到更新

理论上,有人可能会在 之后删除该文件open,导致 utime 引发异常。但可以说这没问题,因为确实发生了一些不好的事情。

解决方案 9:

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

解决方案 10:

以下内容已足够:

import os
def func(filename):
    if os.path.exists(filename):
        os.utime(filename)
    else:
        with open(filename,'a') as f:
            pass

如果要为触摸设置特定时间,请使用 os.utime ,如下所示:

os.utime(filename,(atime,mtime))

这里,atime 和 mtime 都应该是 int/float,并且应该等于您想要设置的时间的纪元时间(以秒为单位)。

解决方案 11:

复杂(可能有缺陷):

def utime(fname, atime=None, mtime=None)
    if type(atime) is tuple:
        atime, mtime = atime

    if atime is None or mtime is None:
        statinfo = os.stat(fname)
        if atime is None:
            atime = statinfo.st_atime
        if mtime is None:
            mtime = statinfo.st_mtime

    os.utime(fname, (atime, mtime))


def touch(fname, atime=None, mtime=None):
    if type(atime) is tuple:
        atime, mtime = atime

    open(fname, 'a').close()
    utime(fname, atime, mtime)

这也尝试允许设置访问或修改时间,就像 GNU touch 一样。

解决方案 12:

创建一个包含所需变量的字符串并将其传递给 os.system 看起来合乎逻辑:

touch = 'touch ' + dir + '/' + fileName
os.system(touch)

这在很多方面都是不够的(例如,它不处理空格),所以不要这样做。

更为强大的方法是使用 subprocess :

subprocess.call(['touch', os.path.join(dirname, fileName)])

虽然这比使用子shell(带有os.system)要好得多,但它仍然只适用于快速而粗糙的脚本;对于跨平台程序,请使用公认的答案。

解决方案 13:

write_text()即可pathlib.Path使用。

>>> from pathlib import Path
>>> Path('aa.txt').write_text("")
0

解决方案 14:

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

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

您可以使用以下方式安装pip install touch

解决方案 15:

你为什么不尝试一下:newfile.py

#!/usr/bin/env python
import sys
inputfile = sys.argv[1]

with open(inputfile, 'r+') as file:
    pass

python 新文件.py foobar.txt

或者

使用子流程:

import subprocess
subprocess.call(["touch", "barfoo.txt"])

解决方案 16:

我有一个用于备份的程序: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 仓库:
https://stromberg.dnsalias.org/svn/touch/trunk
它包含了我尝试过的 4 种触摸方式。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2787  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1710  
  产品配置管理在企业产品研发与生产过程中扮演着至关重要的角色,它能够确保产品在不同阶段的一致性、可追溯性以及高效的变更管理。PLM(产品生命周期管理)系统作为整合产品全生命周期信息的平台,为产品配置管理提供了强大的支持。随着技术的不断发展,到2025年,PLM系统在支持产品配置管理方面将有一系列值得关注的技术实践。基于人...
plm系统主要干什么的   11  
  敏捷迭代周期与 PLM 流程的适配是现代企业在产品开发过程中面临的重要课题。随着市场竞争的加剧和技术的快速发展,企业需要更加高效、灵活的产品开发模式,以满足客户不断变化的需求。敏捷迭代周期强调快速响应变化、持续交付价值,而 PLM 流程则侧重于产品全生命周期的管理和控制。如何将两者有机结合,优化交付节奏,成为提升企业竞...
plm是什么意思   10  
  在企业的数字化转型进程中,PLM(产品生命周期管理)与ERP(企业资源计划)作为两款重要的企业级系统,发挥着关键作用。然而,很多企业人员对它们之间的区别以及协同逻辑并不十分清晰。深入了解这两者的差异与协同方式,有助于企业更好地规划信息化建设,提升整体运营效率。PLM系统概述PLM系统聚焦于产品从概念设计到退役的全生命周...
国产plm软件   12  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用