name files python filenames

files - python package name



¿Es esta la mejor manera de obtener una versión única del nombre de archivo w/Python? (6)

Dos pequeños cambios ...

base_name, ext = os.path.splitext(file_name)

Obtendrá dos resultados con un significado distinto, asígneles nombres distintos.

file_name = "%s_%d%s" % (base_name, str(counter), ext)

No es más rápido o significativamente más corto. Pero, cuando quiera cambiar el patrón de su nombre de archivo, el patrón está en un solo lugar y es un poco más fácil trabajar con él.

Todavía estoy "inmerso" en Python, y quiero asegurarme de que no estoy pasando por alto algo. Escribí un script que extraía archivos de varios archivos zip y guardaba los archivos extraídos en un directorio. Para evitar que los nombres de archivos duplicados se sobrescriban, escribí esta pequeña función, ¿y me pregunto si existe una forma mejor de hacerlo? ¡Gracias!

def unique_filename(file_name): counter = 1 file_name_parts = os.path.splitext(file_name) # returns (''/path/file'', ''.ext'') while os.path.isfile(file_name): file_name = file_name_parts[0] + ''_'' + str(counter) + file_name_parts[1] counter += 1 return file_name

Realmente necesito que los archivos estén en un solo directorio, y la numeración de los duplicados es definitivamente aceptable en mi caso, así que no estoy buscando un método más robusto (aunque supongo que cualquier puntero es bienvenido), pero solo para asegurarme que lo que esto logra se hace de la manera correcta.


Sí, esta es una buena estrategia para nombres de archivo legibles pero únicos.

Un cambio importante : ¡debe reemplazar os.path.isfile con os.path.lexists ! Como está escrito ahora, si hay un directorio llamado /foo/bar.baz, su programa intentará sobrescribirlo con el nuevo archivo (que no funcionará) ... ya que isfile solo busca archivos y no directorios. . lexists busca directorios, enlaces simbólicos, etc. ... básicamente si hay alguna razón por la que no se pueda crear el nombre del archivo.

EDITAR: @Brian dio una mejor respuesta, que es más segura y robusta en términos de condiciones de carrera.


Si quieres nombres legibles, esta parece una buena solución.
Hay rutinas para devolver nombres de archivos únicos, por ejemplo. archivos temporales, pero producen nombres largos de apariencia aleatoria.


Un problema es que hay una condición de carrera en el código anterior, ya que existe una brecha entre la prueba de existencia y la creación del archivo. Puede haber implicaciones de seguridad para esto (piense en alguien que inserta maliciosamente un enlace simbólico a un archivo confidencial que no podría sobrescribir, pero su programa que se ejecuta con un privilegio mayor podría) Ataques como estos son el por qué cosas como os.tempnam ( ) están en desuso.

Para evitarlo, el mejor enfoque es tratar de crear el archivo de tal manera que obtenga una excepción si falla y, en caso de éxito, devolver el objeto de archivo realmente abierto. Esto se puede hacer con las funciones os.open de nivel inferior, pasando las banderas os.O_CREAT y os.O_EXCL. Una vez abierto, devuelve el archivo real (y, opcionalmente, el nombre de archivo) que crees. Por ejemplo, aquí está su código modificado para usar este enfoque (devolviendo una tupla (archivo, nombre de archivo)):

def unique_file(file_name): counter = 1 file_name_parts = os.path.splitext(file_name) # returns (''/path/file'', ''.ext'') while 1: try: fd = os.open(file_name, os.O_CREAT | os.O_EXCL | os.O_RDRW) return os.fdopen(fd), file_name except OSError: pass file_name = file_name_parts[0] + ''_'' + str(counter) + file_name_parts[1] counter += 1

[Editar] En realidad, una mejor manera, que manejará los problemas anteriores para usted, es probablemente utilizar el módulo de tempfile, aunque puede perder cierto control sobre la denominación. Aquí hay un ejemplo de cómo usarlo (manteniendo una interfaz similar):

def unique_file(file_name): dirname, filename = os.path.split(file_name) prefix, suffix = os.path.splitext(filename) fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname) return os.fdopen(fd), filename >>> f, filename=unique_file(''/home/some_dir/foo.txt'') >>> print filename /home/some_dir/foo_z8f_2Z.txt

El único inconveniente de este enfoque es que siempre obtendrá un nombre de archivo con algunos caracteres aleatorios, ya que no hay ningún intento de crear un archivo sin modificar (/home/some_dir/foo.txt) primero. También es posible que desee examinar tempfile.TemporaryFile y NamedTemporaryFile, que hará lo anterior y también eliminará automáticamente del disco cuando se cierre.


si no te importa la legibilidad, uuid.uuid4 () es tu amigo.

import uuid def unique_filename(prefix=None, suffix=None): fn = [] if prefix: fn.extend([prefix, ''-'']) fn.append(str(uuid.uuid4())) if suffix: fn.extend([''.'', suffix.lstrip(''.'')]) return ''''.join(fn)


Qué tal si

def ensure_unique_filename(orig_file_path): from time import time import os if os.path.lexists(orig_file_path): name, ext = os.path.splitext(orig_file_path) orig_file_path = name + str(time()).replace(''.'', '''') + ext return orig_file_path

time () devuelve la hora actual en milisegundos. combinado con el nombre de archivo original, es bastante único, incluso en casos complejos con múltiples subprocesos.