2012-01-05 20 views
11

Necesito actualizar un archivo. Lo leí y lo escribí con los cambios. Sin embargo, preferiría escribir en un archivo temporal y cambiarle el nombre.En python, crea un archivo temporal en el mismo directorio que otro archivo?

temp = tempfile.NamedTemporaryFile() 
tempname = temp.name 
temp.write(new_data) 
temp.close() 
os.rename(tempname, data_file_name) 

El problema es que tempfile.NamedTemporaryFile() hace que el archivo temporal en /tmp que es un sistema de archivos diferente. Esto significa que os.rename() falla. Si uso shlib.move() entonces no tengo la actualización atómica que "mv" ofrece (para archivos en el mismo sistema de archivos, bla, bla, etc.)

tempfile.NamedTemporaryFile() toma un parámetro "dir", pero data_file_name podría ser "foo.txt" en cuyo caso dir = '.'; o data_file_name podría ser "/path/to/the/data/foo.txt" en cuyo caso dir = "/path/to/the/data".

Lo que realmente me gustaría es que el archivo temporal sea data_file_name + "algunos datos aleatorios". Esto tendría el beneficio de fallar de una manera que dejaría pistas útiles.

Sugerencias?

+3

¿Por qué está utilizando un archivo temporal en primer lugar, si no desea que se ponga en el directorio de archivos temporales? ¿Qué habla en contra de usar archivos ordinarios? –

+1

David: Quiero usar un archivo temporal porque quiero que la actualización sea atómica (o tan atómica como pueda ser con os.rename()). Es decir, si el sistema de archivos se llena o hay algún otro problema, no quiero que el archivo esté medio escrito. – TomOnTime

+0

Bueno, esto podría ser difícil de lograr, ya que nunca se sabe realmente, si los archivos escritos en una carpeta diferente están en el mismo sistema de archivos que su directorio local. Veo la ventaja de organizar su salida en algún tipo de compromiso. Para estar relativamente seguro de que este es el caso, probablemente gestionaría mi propio directorio temporal, aunque también se ocuparía de la limpieza de esta carpeta. –

Respuesta

17

Usted puede utilizar:

  • prefix para hacer que el archivo temporal comienzan con el mismo nombre que el archivo original .
  • dir para especificar dónde colocar el archivo temporal.
  • os.path.split para dividir el directorio del nombre de archivo.

import tempfile 
import os 
dirname, basename = os.path.split(filename) 
temp = tempfile.NamedTemporaryFile(prefix=basename, dir=dirname) 
print(temp.name) 
+0

Si filename = 'foo', entonces dirname será ''. Estoy gratamente sorprendido de que NamedTemporaryFile funcione con dir = '' lo mismo que dir = None. ¡Gracias! – TomOnTime

+0

Simplemente para hacer esto explícito: también debe pasar 'delete = False' al constructor NamedTemporaryFile, o el archivo se eliminará al cerrar. – moeffju

2

utilizo el momento actual como "algunos datos aleatorios" anexan a una cadena de base para un nombre de archivo temporal único:

import time 

temp_file_name = data_file_name + str(time.time()) 
+0

Esto es tentador, pero he visto suficientes problemas de seguridad de las personas que crean su propio sistema de archivos temporales que sé que usan el que proporciona tempfile. – TomOnTime

+0

Como nota añadida aquí, unos años más tarde, esto tendrá conflictos si se ejecuta dos veces en el mismo milisegundo, lo que definitivamente es posible en la mayoría de los casos de uso de las personas. Es mejor usar la implementación oficial de tempfile, cosas así y condiciones de carrera cuando intentas evitarlo. – daboross

4

Puede pasar una ubicación de archivo en el parámetro constructor 'dir'. Funciona, como lo desee.

>>> t = tempfile.NamedTemporaryFile(dir="/Users/rafal") 
>>> t.name 
'/Users/rafal/tmplo45Js' 

Fuente: http://docs.python.org/library/tempfile.html#tempfile.NamedTemporaryFile

+2

info: sin 'delete = False' el archivo se elimina tan pronto como se cierra el controlador de archivos. – gecco

+0

Esto supone que sabemos lo que es el directorio. – TomOnTime

+0

Lo sabemos. La pregunta ya de OP contiene dividir una ruta en directorio y nombre de archivo, por lo que es redundante escribir aquí. –

4

para satisfacer todas sus lista de verificación Creo que te gustaría utilizar ...

temp = tempfile.NamedTemporaryFile(prefix=data_file_name, dir=path, 
            delete=False) 

importante tener la delete=False, porque de lo contrario:

[...] Si la eliminación es verdadera (la predeterminada), el archivo se elimina tan pronto como se cierra .

+0

Esto supone que sabemos cuál es el camino. – TomOnTime

-1

El módulo tempfile que utiliza proporciona una forma segura de administrar los archivos temporales. Si realmente quieres usar tu propio sistema, debes ser consciente de que podría ser vulnerable a ataques (particularmente ataques de enlace simbólico).

Una forma sencilla de generar un nombre de archivo único temporal (aunque un nombre bastante largo) es:

import uuid 
import os 

tempfilename = 'myprefix-%s.dat' % str(uuid.uuid4()) 

with open(tempfilename, 'rw') as tempfile: 
    # do stuff 

os.remove(tempfilename) 

Pero esto es un poco hacker; realmente más bien considere usar el módulo tempfile con los parámetros prefix y dir correctos pasados ​​a NamedTemporaryFile, como se describe en las otras respuestas.

+0

Esto es tentador, pero he visto suficientes problemas de seguridad causados ​​por personas que crean su propio sistema de archivos temporales que sé que usan el que proporciona tempfile. – TomOnTime

+0

Absolutamente, usar algo como esto es una mala idea en el código de producción. En un entorno donde esto no es una preocupación (por ejemplo, el registro de datos de simulación), 'uuid' presenta una forma de generar una cadena aleatoria única. –

Cuestiones relacionadas