Python: ¿Cómo crear un nombre de archivo único?

95

Tengo un formulario web de Python con dos opciones: carga de archivos y área de texto . Necesito tomar los valores de cada uno y pasarlos a otro programa de línea de comandos. Puedo pasar fácilmente el nombre del archivo con las opciones de carga de archivos, pero no estoy seguro de cómo pasar el valor del área de texto.

Creo que lo que tengo que hacer es:

  1. Genere un nombre de archivo único
  2. Cree un archivo temporal con ese nombre en el directorio de trabajo
  3. Guarde los valores pasados ​​de textarea en el archivo temporal
  4. Ejecute el programa de línea de comandos desde el interior de mi módulo de Python y páselo el nombre del archivo temporal

No estoy seguro de cómo generar un nombre de archivo único. ¿Alguien puede darme algunos consejos sobre cómo generar un nombre de archivo único? Se agradece cualquier algoritmo, sugerencia y línea de código.

Gracias por tu preocupación

MysticCodes
fuente
1
Edité tu pregunta para intentar aclararla. ¡Avísame si interpreté algo incorrectamente!
culix

Respuestas:

147

No creo que tu pregunta sea muy clara, pero si todo lo que necesitas es un nombre de archivo único ...

import uuid

unique_filename = str(uuid.uuid4())
EnigmaCurry
fuente
Lo siento, estoy trabajando en la plataforma de Windows, así que no sé cómo manejar el subproceso
MysticCodes
uuid parece crear una cadena larga y única. No creo que sea mejor tener un nombre de archivo con una cadena larga y UUID, () en él.
MysticCodes
6
Creo que uuid.uuid4().hexsería una mejor opción, ver detalles aquí .
Gray Li
4
@ToloPalmer: Es más probable que la CPU de su computadora tenga un error de procesamiento que haga que cargue el archivo incorrecto que si un UUID generado choca con cualquier valor existente. UUID produce un nombre único en un modelo de computación que entiende que no toda la computación es pura matemática.
GManNickG
2
Disculpe mi ignorancia, el comentario anterior ... De hecho, no es único, pero es muy poco probable que choque, por lo que es una buena elección;)
Tolo Palmer
51

Si desea crear archivos temporales en Python, hay un módulo llamado tempfile en las bibliotecas estándar de Python. Si desea ejecutar otros programas para operar en el archivo, use tempfile.mkstemp () para crear archivos y os.fdopen () para acceder a los descriptores de archivo que le proporciona mkstemp ().

Por cierto, ¿dice que está ejecutando comandos desde un programa de Python? Es casi seguro que debería utilizar el módulo de subproceso .

Por lo que puede escribir código con bastante alegría que se parece a:

import subprocess
import tempfile
import os

(fd, filename) = tempfile.mkstemp()
try:
    tfile = os.fdopen(fd, "w")
    tfile.write("Hello, world!\n")
    tfile.close()
    subprocess.Popen(["/bin/cat", filename]).wait()        
finally:
    os.remove(filename)

Al ejecutar eso, debería encontrar que el catcomando funcionó perfectamente bien, pero el archivo temporal se eliminó en el finallybloque. Tenga en cuenta que usted tiene que borrar el archivo temporal que mkstemp () devuelve a sí mismo - la biblioteca no tiene manera de saber cuando haya terminado con él!

(Editar: había supuesto que NamedTemporaryFile hizo exactamente lo que buscas, pero eso podría no ser tan conveniente: el archivo se elimina inmediatamente cuando se cierra el objeto del archivo temporal y otros procesos abren el archivo antes de cerrarlo. no funcionará en algunas plataformas, especialmente Windows. Lo siento, fallaré de mi parte).

Richard Barrell
fuente
usar NamedTemporaryFile es probablemente lo que quieren (a menos que quieran que permanezca en el servidor, y luego pueden usar "tempfile.NamedTemporaryFile (delete = False)")
Terence Honles
¿Puedo hacer que ese nombre de archivo temporal también sea único? para que pueda guardarlo más tarde cuando el subproceso se complete con un nombre único
MysticCodes
@Terence Honles: Originalmente sugerí tempfile.NamedTemporaryFile (), pero realmente no puede usarlo para crear archivos temporales a los que otros procesos puedan acceder en Windows. Sin embargo, NamedTemporaryFile (delete = False) ciertamente es más limpio . @ user343934: tempfile.mkstemp () está garantizado para darle un nombre único cada vez que es llamado - genera los nombres al azar y usa las instalaciones del sistema operativo (O_EXCL, si se lo está preguntando) para evitar colisiones.
Richard Barrell
wow, no sabía que no funcionaba en Windows ... falla :( ... Supongo que es bueno saberlo
Terence Honles
@Terence Honles: NamedTemporaryFile () en realidad no falla en Windows (hasta donde yo sé), pero no puede cerrar el archivo sin eliminarlo también, y (según tengo entendido la semántica del archivo en Windows) ningún otro programa puede abrir el archivo mientras lo tiene abierto. Podría estar equivocado; la semántica para tener múltiples procesos que comparten un archivo en Windows podría haber cambiado desde la última vez que verifiqué.
Richard Barrell
32

El uuidmódulo sería una buena opción, prefiero usar uuid.uuid4().hexcomo nombre de archivo aleatorio porque devolverá una cadena hexadecimal sin guiones .

import uuid
filename = uuid.uuid4().hex

Las salidas deberían tener este aspecto:

>>> import uuid
>>> uuid.uuid()
UUID('20818854-3564-415c-9edc-9262fbb54c82')
>>> str(uuid.uuid4())
'f705a69a-8e98-442b-bd2e-9de010132dc4'
>>> uuid.uuid4().hex
'5ad02dfb08a04d889e3aa9545985e304'  # <-- this one
Li gris
fuente
1
¿Cuál es el problema de tener guiones?
David Lopez
15

¿Quizás necesitas un archivo temporal único?

import tempfile

f = tempfile.NamedTemporaryFile(mode='w+b', delete=False)

print f.name
f.close()

f es un archivo abierto. delete=Falsesignifica no borrar el archivo después de cerrarlo.

Si necesita controlar el nombre del archivo, hay argumentos opcionales prefix=...y suffix=...que toman cadenas. Consulte https://docs.python.org/3/library/tempfile.html .

Роман Буртник
fuente
Esto es genial si no necesita controlar el nombre del archivo.
hiwaylon
1
Debería ser tmpfile.NamedTemporaryFile no solo NamedTemporaryFile.
user1993015
w+bes el predeterminado mode. El uso de cualquier tempfilefuncionalidad tiene la desventaja de los permisos de acceso a archivos incorrectos: tempfiledocumentos para usar os.O_TMPFILEcomo máscara, pero respeta la creación normal de archivos os.umask().
m8mble
8

Puedes usar el módulo de fecha y hora

import datetime
uniq_filename = str(datetime.datetime.now().date()) + '_' + str(datetime.datetime.now().time()).replace(':', '.')

Tenga en cuenta que: lo estoy usando replaceya que los dos puntos no están permitidos en los nombres de archivo en muchos sistemas operativos.

Eso es todo, esto le dará un nombre de archivo único cada vez.

Nimish Agrawal
fuente
2
A menos que los nombres de archivo se creen inmediatamente uno después del otro (por ejemplo, en un bucle). Entonces son iguales.
skjerns
1

Me encontré con esta pregunta y agregaré mi solución para aquellos que puedan estar buscando algo similar. Mi enfoque fue simplemente hacer un nombre de archivo aleatorio a partir de asciicaracteres. Será único con una buena probabilidad.

from random import sample
from string import digits, ascii_uppercase, ascii_lowercase
from tempfile import gettempdir
from os import path

def rand_fname(suffix, length=8):
    chars = ascii_lowercase + ascii_uppercase + digits

    fname = path.join(gettempdir(), 'tmp-'
                + ''.join(sample(chars, length)) + suffix)

    return fname if not path.exists(fname) \
                else rand_fname(suffix, length)
behzad.nouri
fuente
1
La respuesta obvia a la pregunta tenía que ver con el paquete uuid. Sin embargo, mi servidor de destino tiene Python 2.4, ningún paquete uuid y el propietario del servidor no autorizó la actualización debido a incompatibilidades de software heredado, por lo que esta respuesta me funciona.
Alberto Gaona
1
Me gusta particularmente esta respuesta: se puede ajustar fácilmente a las especificaciones del proyecto.
swdev
1
1) No hay razón para usar la recursividad aquí, especialmente sin límites. 2) Existe una condición de carrera entre el momento en que path.exists()regresa Falsey el momento en que un consumidor abre realmente el archivo.
Jonathon Reinhart
1

Esto se puede hacer usando la función única en el módulo ufp.path .

import ufp.path
ufp.path.unique('./test.ext')

si existe la ruta actual, el archivo 'test.ext'. La función ufp.path.unique devuelve './test (d1) .ext'.

c2o93y50
fuente
6
ufp es parte de drupal? no es un módulo estándar
endolito
1

Para crear una ruta de archivo única, si existe, use el paquete aleatorio para generar un nuevo nombre de cadena para el archivo. Puede consultar el siguiente código para el mismo.

import os
import random
import string

def getUniquePath(folder, filename):    
    path = os.path.join(folder, filename)
    while os.path.exists(path):
         path = path.split('.')[0] + ''.join(random.choice(string.ascii_lowercase) for i in range(10)) + '.' + path.split('.')[1]
    return path

Ahora puede usar esta ruta para crear un archivo en consecuencia.

RoboMex
fuente
1

En caso de que necesite ID únicos breves como nombre de archivo, intente shortuuid, shortuuid usa letras minúsculas y mayúsculas y dígitos, y elimina caracteres de apariencia similar como l, 1, I, O y 0.

>>> import shortuuid
>>> shortuuid.uuid()
'Tw8VgM47kSS5iX2m8NExNa'
>>> len(ui)
22

comparado con

>>> import uuid
>>> unique_filename = str(uuid.uuid4())
>>> len(unique_filename)
36
>>> unique_filename
'2d303ad1-79a1-4c1a-81f3-beea761b5fdf'
Milind Deore
fuente