google enseña python utility

google enseña python



¿Implementar el toque usando Python? (11)

touch es una utilidad de Unix que establece las horas de modificación y acceso de los archivos a la hora actual del día. Si el archivo no existe, se crea con los permisos predeterminados.

¿Cómo lo implementarías como una función de Python? Intenta ser multiplataforma y completa.

(Los resultados actuales de Google para "python touch file" no son tan buenos, pero apuntan a os.utime ).


"open (file_name, ''a''). close ()" no me funcionó en Python 2.7 en Windows. "os.utime (file_name, None)" funcionó bien.

Además, tuve la necesidad de tocar de forma recursiva todos los archivos en un directorio con una fecha anterior a alguna fecha. He creado hte siguiente basado en la respuesta muy útil de efímero.

def touch(file_name): # Update the modified timestamp of a file to now. if not os.path.exists(file_name): return try: os.utime(file_name, None) except Exception: open(file_name, ''a'').close() def midas_touch(root_path, older_than=dt.now(), pattern=''**'', recursive=False): '''''' midas_touch updates the modified timestamp of a file or files in a directory (folder) Arguements: root_path (str): file name or folder name of file-like object to touch older_than (datetime): only touch files with datetime older than this datetime pattern (str): filter files with this pattern (ignored if root_path is a single file) recursive (boolean): search sub-diretories (ignored if root_path is a single file) '''''' # if root_path NOT exist, exit if not os.path.exists(root_path): return # if root_path DOES exist, continue. else: # if root_path is a directory, touch all files in root_path if os.path.isdir(root_path): # get a directory list (list of files in directory) dir_list=find_files(root_path, pattern=''**'', recursive=False) # loop through list of files for f in dir_list: # if the file modified date is older thatn older_than, touch the file if dt.fromtimestamp(os.path.getmtime(f)) < older_than: touch(f) print "Touched ", f # if root_path is a file, touch the file else: # if the file modified date is older thatn older_than, touch the file if dt.fromtimestamp(os.path.getmtime(f)) < older_than: touch(root_path)


¿Por qué no probar esto ?:

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

Creo que esto elimina cualquier condición de raza que importa. Si el archivo no existe, se lanzará una excepción.

La única condición de carrera posible aquí es si el archivo se crea antes de llamar a open () pero después de os.utime (). Pero esto no importa porque en este caso el tiempo de modificación será el esperado, ya que debe haber ocurrido durante la llamada a touch ().


Aquí hay un código que usa ctypes (solo probado en 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())


Complejo (posiblemente buggy):

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)

Esto intenta permitir también configurar el tiempo de acceso o modificación, como GNU touch.


Esto intenta ser un poco más libre de carreras que las otras soluciones. (La palabra clave with es nueva en Python 2.5).

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

Aproximadamente equivalente a esto.

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

Ahora, para que sea realmente libre de carreras, debe usar futimes y cambiar la marca de tiempo del futimes archivo abierto, en lugar de abrir el archivo y luego cambiar la marca de tiempo en el nombre de archivo (que puede haber sido renombrado). Desafortunadamente, Python no parece proporcionar una manera de llamar a los futimes sin pasar por ctypes o similares ...

EDITAR

Como lo señaló Nate Parsons , Python 3.3 add especificación de un descriptor de archivo (cuando os.supports_fd ) a funciones como os.utime , que usará el futimes syscall en lugar del utimes syscall debajo del capó. En otras palabras:

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)


Parece que esto es nuevo a partir de Python 3.4 - pathlib .

from pathlib import Path Path(''path/to/file.txt'').touch()

Esto creará un file.txt en la ruta.

-

Path.touch (mode = 0o777, exist_ok = True)

Crear un archivo en esta ruta dada. Si se da el modo, se combina con el valor de umask del proceso para determinar el modo de archivo y las banderas de acceso. Si el archivo ya existe, la función tiene éxito si exist_ok es verdadero (y su hora de modificación se actualiza a la hora actual), de lo contrario, se genera FileExistsError.


Puede parecer lógico crear una cadena con las variables deseadas y pasarla a os.system:

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

Esto es inadecuado de varias maneras (por ejemplo, no maneja espacios en blanco), así que no lo hagas.

Un método más robusto es utilizar el subproceso:

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

Si bien esto es mucho mejor que usar una subshell (con os.system), todavía es adecuado solo para scripts rápidos y sucios; Utilice la respuesta aceptada para programas multiplataforma.


Simplista:

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

  • El open asegura que hay un archivo allí.
  • el utime asegura que las marcas de tiempo se actualizan

Teóricamente, es posible que alguien elimine el archivo después de open , lo que provocará que utime genere una excepción. Pero podría decirse que está bien, ya que algo malo sucedió.


Esta respuesta es compatible con todas las versiones desde Python-2.5 cuando se ha lanzado una palabra clave with .

1. Crear archivo si no existe + Establecer hora actual
(exactamente igual que el comando de 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

Una versión más robusta:

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. Solo crea el archivo si no existe
(no actualiza la hora)

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

3. Sólo actualizar el acceso a los archivos / tiempos modificados
(no crea archivo si no existe)

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

Usar os.path.exists() no simplifica el código:

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)

Bonus: Tiempo de actualización de todos los archivos en un directorio

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)


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


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