2010-06-02 25 views
51

Tengo un formulario web de Python con dos opciones: Carga de archivos y textarea. 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.Python: ¿Cómo crear un nombre de archivo único?

Creo que lo que tengo que hacer es:

  1. generar un nombre de archivo único
  2. Crear un archivo temporal con ese nombre en el directorio de trabajo
  3. Guardar los valores pasados ​​de área de texto en el temporal el archivo
  4. ejecutar el programa de línea de comandos desde el interior de mi módulo de Python y pasarle 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 agradecen todos los algoritmos, sugerencias y líneas de código.

Gracias por su preocupación

+1

edité su pregunta para tratar de hacerla más clara. ¡Avíseme si interpreté algo incorrectamente! – culix

Respuesta

82

No pensé que usted ha sido muy clara, pero si todo lo que necesita es un nombre de archivo único ...

import uuid 

unique_filename = str(uuid.uuid4()) 
+0

¿Debería volver a editar mi pregunta de una manera más comprensiva? – MysticCodes

+0

Lo siento, estoy trabajando en la plataforma de Windows, así que no sé cómo manejar el subproceso – MysticCodes

+0

uuid parece crear una larga cadena única. No creo que sea mejor tener un nombre de archivo con cadena larga y UUID,() en él. – MysticCodes

41

Si desea hacer que los 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 archivos que le proporciona mkstemp().

Por cierto, dices que estás ejecutando comandos desde un programa de Python? Casi seguramente deberías estar usando el módulo subprocess.

Así que usted puede bastante alegremente escribir código 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) 

Ejecución de eso, usted debe encontrar que el comando cat trabajó perfectamente bien, pero el archivo temporal ha sido eliminada en el bloque finally. Tenga en cuenta que tiene para eliminar el archivo temporal que mkstemp() devuelve usted mismo: ¡la biblioteca no tiene manera de saber cuándo ha terminado!

(Editar: Yo había supuesto que NamedTemporaryFile hizo exactamente lo que está buscando, pero eso podría no ser tan conveniente: el archivo se elimina inmediatamente cuando el archivo temporal está cerrado y tiene otros procesos para abrir el archivo. 'Cerrado no funcionará en algunas plataformas, notablemente Windows. Lo siento, fallo de mi parte.)

+0

usando ** NamedTemporaryFile ** es probablemente lo que quieren (a menos que quieran permanecer en el servidor, y luego pueden usar "tempfile.NamedTemporaryFile (delete = False)") –

+0

¿Puedo hacer que el nombre de archivo temporal también sea único? entonces puedo guardarlo más tarde cuando el subproceso se completa con el nombre único – MysticCodes

+0

@Terence Honles: sugerí tempfile.NamedTemporaryFile() originalmente, pero realmente no se puede usar para crear archivos temporales a los que otros procesos puedan acceder en Windows. NamedTemporaryFile (delete = False) ciertamente es * cleaner *, sin embargo. @ user343934: tempfile.Se garantiza que mkstemp() le dará un nombre único cada vez que se llame: genera los nombres aleatoriamente y usa las funciones del sistema operativo (O_EXCL, si se lo está preguntando) para evitar colisiones. –

2

Me encontré con esta pregunta, y voy a agregar mi solución para aquellos que pueden estar buscando algo similar. Mi enfoque era simplemente hacer un nombre de archivo aleatorio de ascii caracteres. 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) 
+1

La respuesta obvia para 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 la actualización no fue autorizada por el propietario del servidor debido a las incompatibilidades de software heredado, por lo que esta respuesta funciona para mí. –

+1

Me gusta especialmente esta respuesta: se puede ajustar fácilmente a las especificaciones del proyecto. – swdev

+0

1) No hay ninguna razón para usar la recursión aquí, especialmente sin límites. 2) Existe una condición de carrera entre el momento en que 'path.exists()' devuelve 'False' y el momento en que un consumidor realmente abre el archivo. –

8

Tal vez necesita un archivo temporal único?

import tempfile 

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

print f.name 
f.close() 

f es el archivo abierto. delete=False significa no borrar el archivo después del cierre.

+0

Esto es genial si no necesita controlar el nombre del archivo. – hiwaylon

+1

Debe ser tmpfile.NamedTemporaryFile no solo NamedTemporaryFile. – user1993015

2

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

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

si la ruta actual existe 'test.ext' file. ufp.path.unique function return './test (d1) .ext'.

ver ejemplo: Generate unique path at filepath or dirpath [Python]

+2

ufp es parte de drupal? no es un módulo estándar – endolith

2

Usted puede utilizar el módulo datetime

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

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

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

6

El módulo uuid sería una buena opción, yo prefiero usar uuid.uuid4().hex nombre de archivo como al azar, ya que volverá una cadena hexadecimal sin guiones.

import uuid 
filename = uuid.uuid4().hex 

Las salidas deben desea:

>>> import uuid 
>>> uuid.uuid() 
UUID('20818854-3564-415c-9edc-9262fbb54c82') 
>>> str(uuid.uuid4()) 
'f705a69a-8e98-442b-bd2e-9de010132dc4' 
>>> uuid.uuid4().hex 
'5ad02dfb08a04d889e3aa9545985e304' # <-- this one 
Cuestiones relacionadas