2011-11-12 8 views
33

¿Es posible forzar un cambio de nombre os.rename para sobrescribir otro archivo si ya existe? Por ejemplo, en el código siguiente si el archivo Tests.csv ya existe, se reemplazará por el archivo Tests.txt (que también se renombró a Tests.csv).Forzar sobrescritura en Os.Rename

os.rename("C:\Users\Test.txt","C:\Users\Tests.csv"); 
+0

¿Qué le parece desvincular primero el archivo de destino, atrapando una posible excepción? –

+2

Recuerde siempre escapar de las barras diagonales inversas en cadenas (por ejemplo, use '" C: \\ Users \\ Test.txt "') – 6502

+1

... o use 'r" C: \ Users \ Test.txt "', pero tenga cuidado con 'r" C: \\ "'. –

Respuesta

24

Usted podría intentar shutil.move():

from shutil import move 

move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 

O os.remove y luego shutil.move:

from os import remove 
from shutil import move 

remove('C:\\Users\\Tests.csv') 
move('C:\\Users\\Test.txt', 'C:\\Users\\Tests.csv') 
+0

@JohnZwinck: no, esto funciona en Windows mientras 'os.rename' no. Ver ['código fuente shutil.move'] (http://hg.python.org/cpython/file/9b26fa7f9adf/Lib/shutil.py#l298). –

+1

Bueno, +1 de mí por la respuesta actual, aunque sospecho que esto puede dar lugar a una condición de carrera. De las otras respuestas, creo que esto es inevitable en Windows. –

+0

la pregunta pregunta "... si existe ...", por lo que eliminar debe ser envuelto con si o probar la lógica – denfromufa

0

A partir de la documentación de la biblioteca estándar “, en Windows, si el horario de verano ya existe, OSError será levantado incluso si es un archivo; puede que no haya manera de implementar un cambio de nombre atómica cuando los nombres dst un archivo existente “

http://docs.python.org/library/os.html#os.rename

Así que la única solución, por desgracia, serían para cambiar los sistemas operativos.; Windows simplemente no permite rename() encima de un archivo existente.

7

En Unix, si existe dst y es un archivo, se reemplazará silenciosamente si el usuario tiene permiso. La operación puede fallar en algunos sabores de Unix si src y dst están en diferentes sistemas de archivos. Si tiene éxito, el cambio de nombre será una operación atómica (este es un requisito POSIX). En Windows, si ya existe, OSError se levantará aunque sea un archivo; puede que no haya forma de implementar un cambio de nombre atómico cuando dst nombra un archivo existente. http://docs.python.org/library/os.html#os.rename

+6

otra razón por la que Windows debería ser desterrado de la tierra – MFB

+0

O no porque esto sea completamente incorrecto, la API MoveFile es atómica – paulm

2

Curiosamente, la documentación para os.rename() dice que hace sustituir el objetivo en los sistemas Unix, pero en Windows no lo hace. Mencionan algo vago acerca de que es imposible implementar el cambio de nombre atómico si el destino existe en Windows, que IMO es razón suficiente para no apoyarlo.

Debería detectar OSError (el destino existe en Windows) y eliminar el destino e intentar nuevamente, supongo.

8

A medida que el documentation dice que es imposible garantizar una operación de cambio de nombre atómica en Windows si el archivo existe así que lo que hace es Python pidiendo que haga el doble paso os.remove + os.rename mismo, el manejo de errores potenciales.

En los sistemas Unix rename sobrescribe el destino si existe (porque se garantiza que la operación es atómica).

Tenga en cuenta que en Windows también es posible que falle la eliminación del archivo de destino incluso si tiene permiso porque el archivo puede estar en uso. Esta es otra limitación esencial del sistema de archivos de Windows y debe manejarlo usted mismo en el código.

19

Como Python 3.3, ahora hay una solución multiplataforma estándar, os.replace:

Cambie el nombre del archivo o directorio src a DST. Si dst es un directorio, OSError será elevado. Si existe dst y es un archivo, se reemplazará silenciosamente si el usuario tiene permiso .La operación puede fallar si src y dst están en sistemas de archivos diferentes. Si tiene éxito, el cambio de nombre será una operación atómica (este es un requisito POSIX).

Disponibilidad: Unix, Windows.

Nuevo en la versión 3.3.

Sin embargo, al contrario de la documentación, en Windows no se garantiza que sea atómico (en Python 3.4.4). Esto se debe a que internally usa MoveFileEx en Windows, lo que no ofrece tal garantía.

+0

¿Cómo es MoveFileEx no atómico? – paulm

+0

@paulm Si revisa su página MSDN, nunca promete atomicidad e incluso sugiere explícitamente 'MoveFileTransacted' como alternativa. En la práctica, 'MoveFileEx' es atómico en los sistemas de archivos locales pero no atómico en los sistemas de archivos de red (bueno, en realidad depende del servidor). Pero incluso para FSEs locales, su atomicidad no es contractual. – atzz

Cuestiones relacionadas