Cómo copiar un archivo en Python

Cuando se trata de usar Python para copiar archivos, hay dos formas principales: usar el módulo shutil o el módulo os. Todos los métodos os que mostramos aquí son métodos...

Introducción

Cuando se trata de usar Python para copiar archivos, hay dos formas principales: usar el módulo shutil o el módulo os. Todos los métodos os que mostramos aquí son métodos que nos permiten ejecutar comandos de shell desde nuestro código Python, que usaremos para ejecutar el comando copy (Windows) o el comando cp (Unix).

Notarás que muchos de estos métodos, tanto en el módulo ‘shutil’ como en el módulo ‘os’, tienen una funcionalidad muy similar (lo que no debería sorprender), pero cada uno varía ligeramente en funcionalidad entre sí, que voy a explicar también.

Copiar archivos con el módulo Shutil {#copiar archivos con el módulo Shutil}

El módulo de cierre ofrece varios métodos de alto nivel para copiar archivos. A continuación se muestran los principales:

copiar archivo

Este método copia el contenido de un archivo en otro archivo. El destino proporcionado debe ser un archivo grabable y tener un nombre diferente al del archivo de origen. Si los nombres son los mismos, generará un error. Si el archivo de destino ya existe, se reemplazará con el archivo recién copiado.

La sintaxis de este método es:

1
shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

Por ejemplo, el siguiente código copiará un archivo llamado "archivo1.txt" en un archivo llamado "archivo2.txt":

1
2
3
import shutil

shutil.copyfile('file1.txt', 'file2.txt')

Una característica interesante y potencialmente útil de shutil.copyfile es el argumento booleano follow_symlinks. Si se establece en False y el archivo de origen es un enlace simbólico, en lugar de copiar el archivo, se creará un nuevo enlace simbólico.

Copiar

Este método es muy similar a copyfile, con la principal diferencia de que, además de copiar el contenido del archivo de origen, va un paso más allá y también copia los permisos del sistema de archivos del archivo. Copiar permisos de archivos no es una tarea trivial en la mayoría de los lenguajes de programación, por lo que es una buena característica.

La sintaxis es la siguiente:

1
shutil.copy(src_file, dest_file, *, follow_symlinks=True)

Cada uno de estos parámetros son los mismos que en el método copyfile. Por ejemplo, el siguiente código copiará "archivo1.txt" en "archivo3.txt".

1
2
3
import shutil

shutil.copy('file1.txt', 'file3.txt')

Nota: asegúrese de no nombrar su secuencia de comandos igual que uno de los módulos que está importando (lo cual hice por error al probar el código para este artículo). Si lo hace, obtendrá un error al intentar importar ese módulo debido a un problema de importación circular.

copia2

Al igual que con los métodos anteriores, el método copy2 es idéntico al método copy, pero además de copiar el contenido del archivo, también intenta conservar todos los metadatos del archivo fuente. Si la plataforma no permite guardar los metadatos completos, copy2 no devuelve el error y solo conservará todos los metadatos que pueda.

La sintaxis es la siguiente:

1
shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

Nuevamente, estos parámetros son los mismos que en los comandos anteriores que hemos mencionado hasta ahora.

Por ejemplo, el siguiente código copiará "archivo1.txt" en "archivo4.txt", y conservará los metadatos del archivo original, "archivo1.txt".

1
2
3
import shutil

shutil.copy2('file1.txt', 'file4.txt')
1
2
3
4
5
6
7
$ python copy-files.py 
$ ls -l
total 32
-rw-r--r--  1 scott  staff  91 Oct 27 11:26 copy-files.py
-rw-r--r--  1 scott  staff   6 Oct 27 11:27 file1.txt
-rw-r--r--  1 scott  staff   6 Oct 27 11:29 file3.txt
-rw-r--r--  1 scott  staff   6 Oct 27 11:27 file4.txt

Como podemos ver al ejecutar nuestro código anterior, "file1.txt" se copió en "file4.txt". Sin embargo, es posible que haya notado que la fecha de creación se conservó en el nuevo archivo, a diferencia de shutil.copy, que copió "file1.txt" a "file3.txt" y le dio una nueva fecha de creación.

copyfileobj

Este método copia el contenido de un archivo de origen en un archivo de destino, desde la posición actual del archivo de origen. Lo que esto significa es que si lee datos de su objeto de archivo fuente, entonces la posición en la que deja de leer es la posición desde la que copyfileobj comienza a copiar.

La sintaxis es la siguiente:

1
shutil.copyfileobj(src_file_object, dest_file_object[, length])

Los significados de los parámetros del archivo de origen y destino son similares a los de los comandos anteriores, pero ahora se refieren a objetos. El parámetro de longitud es opcional y representa el tamaño del búfer, que es el número de bits guardados en la memoria durante el proceso de copia. Esta opción puede resultar útil al copiar archivos muy grandes, ya que puede acelerar el proceso de copia y evita el uso descontrolado de la memoria.

Por ejemplo, el siguiente código copiará "file1.txt" en "file5.txt"

1
2
3
4
5
6
7
8
9
import shutil

filename1 = 'file1.txt'
fileA = open(filename1, 'rb')

filename2 = 'file5.txt'
fileB = open(filename2, 'wb')

shutil.copyfileobj(fileA, fileB)

Como podemos ver, para usar copyfileobj, necesitamos abrir los archivos en modo binario (que es la parte "b" de "rb" y "wb"). Además, el archivo de origen debe abrirse como legible y el archivo de destino debe abrirse como escribible (las partes "r" y "w", respectivamente).

Copiar archivos con el módulo os {#copiar archivos con el módulo os}

El módulo del sistema operativo proporciona una manera de usar la funcionalidad del sistema operativo para copiar sus archivos. En la mayoría (si no en todos) de los ejemplos de aquí en adelante, proporcionamos ejemplos que funcionan tanto para Windows como para Unix. Los ejemplos son diferentes debido a los comandos de shell utilizados, así que asegúrese de prestar atención a cómo se etiqueta cada llamada de función en los comentarios de Python.

papa

Este método abre una tubería hacia o desde su comando. Sin embargo, tenga en cuenta que este método quedó obsoleto en Python 2.6, por lo que no recomendamos usarlo a menos que sea necesario. Como alternativa, la documentación de Python nos aconseja utilizar métodos del módulo de subproceso.

La sintaxis es la siguiente:

1
os.popen(cmd[, mode[, bufsize]])

Aquí el valor devuelto es un objeto de archivo que está conectado a la tubería. Este objeto se puede leer o escribir dependiendo del modo. El modo predeterminado es 'r', que permite leer el contenido del archivo.

El siguiente ejemplo copiará "archivo1.txt" en "archivo6.txt":

1
2
3
4
5
6
7
import os

# Windows
os.popen('copy file1.txt file6.txt')

# Unix
os.popen('cp file1.txt file6.txt')

Ejecutar el comando de esta manera es exactamente lo mismo que si lo ejecutara directamente desde la línea de comandos de su terminal.

sistema

Este método ejecuta el comando especificado en una subcapa. Está disponible tanto para Unix como para Windows. La sintaxis es la siguiente:

1
os.system(command)

Aquí comando es una cadena que contiene el comando de shell de DOS o Unix. En nuestro caso, aquí es donde colocaremos el comando copy o cp.

Por ejemplo, el siguiente código copiará "file1.txt" en "file7.txt"

1
2
3
4
5
6
7
import os

# Windows
os.system('copy file1.txt file7.txt')

# Unix
os.system('cp file1.txt file7.txt')

Esto parece idéntico al comando os.popen anterior que acabamos de usar, pero el comando se ejecuta en una subcapa, lo que significa que se ejecuta en un subproceso separado en paralelo a su código de ejecución. Para esperar a que se complete, debe llamar a .wait() en el objeto devuelto por os.system.

Copiar archivos con el módulo de subproceso {#copiar archivos con el módulo de subproceso}

El módulo de subproceso intenta reemplazar algunos métodos en el módulo os (particularmente os.system y os.spawn* métodos), y presenta dos métodos principales para acceder a los comandos del sistema operativo. Estos métodos son call y check_output. Una vez más, para los sistemas Unix, el comando "copiar archivo1.txt archivo2.txt" debe reemplazarse por "cp archivo1.txt archivo2.txt".

Método de llamada {#método de llamada}

La documentación de Python nos recomienda usar el método call para lanzar un comando desde el sistema operativo.

La sintaxis es la siguiente:

1
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

El parámetro args incluirá nuestro comando de shell. Sin embargo, una palabra de precaución, ya que la documentación de Python nos advierte que usar shell=True puede ser un riesgo para la seguridad.

Usando esta llamada de función, podemos ejecutar nuestro comando de copia de la siguiente manera:

1
2
3
4
5
6
7
import subprocess

# Windows
status = subprocess.call('copy file1.txt file8.txt', shell=True)

# Unix
status = subprocess.call('cp file1.txt file8.txt', shell=True)

Como muestra el ejemplo anterior, simplemente necesitamos pasar una cadena con el comando shell, como antes.

Y como era de esperar, el sistema operativo copiará "archivo1.txt" en un archivo llamado "archivo8.txt".

método check_output

Este método también nos permite ejecutar un comando dentro de un shell. Es muy parecido al comando subprocess.run, excepto que, de forma predeterminada, canaliza los datos desde la salida estándar como bytes codificados. La sintaxis es la siguiente:

1
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

Aquí el parámetro args incluye el comando de shell que queremos usar. Una vez más, la documentación de Python nos advierte sobre el uso de shell=True, así que use este método con precaución.

En el siguiente código, copiaremos "file1.txt" a "file9.txt" usando el comando check_output:

1
2
3
4
5
6
7
import subprocess

# Windows
status = subprocess.check_output('copy file1.txt file9.txt', shell=True)

# Unix
status = subprocess.check_output('cp file1.txt file9.txt', shell=True)

Y como con todos los comandos que hemos mostrado en este artículo, esto copiará el archivo "archivo1.txt" al destino que especificamos, que es "archivo9.txt" aquí.

Finalizando

Python nos ofrece muchas formas diferentes de copiar archivos, algunas de las cuales son parte del conjunto de métodos de Python. Otros usan algunos de los poderosos métodos de Python para ejecutar comandos en un shell, que utilizan comandos de shell como copy o cp.

¿No estás seguro de cuál es el adecuado para ti? Presentamos muchas formas diferentes de copiar archivos aquí, por lo que es comprensible. El método que utilice para copiar un archivo depende completamente de usted y dependerá de sus necesidades específicas. Aunque en la mayoría de los casos uno de los comandos shutil funcionará bien para ti. Intente comenzar con shutil.copy2 y vea si eso hace lo que necesita.

¿Qué método usas y por qué? ¡Cuéntanos en los comentarios!