Nine ways to copy files in Python

Keywords: Python Windows Linux shell

Python has many ready to eat modules (such as os, subprocess, and shutil) to support file I/O operations. In this article, you'll see some special ways to copy files in Python. Let's start to learn these nine different ways to implement Python copy file operation.

Before you start, you have to understand why it's so important to understand the Python copy file method that works best for you. This is because file I/O operations are performance intensive and often reach bottlenecks. That's why you should choose the best approach based on the design of your application.

Some programs that share resources tend to copy files in blocking mode, while others may want to execute asynchronously. For example - use threads to copy files or start separate processes to implement it. Another point to consider is the portability of the platform. This means that you should know the target operating system (Windows/Linux/Mac OS X, etc.) of the program you want to run.

Nine ways to copy files in Python are as follows:

  • shutil copyfile() method
  • shutil copy() method
  • shutil copyfileobj() method
  • shutil copy2() method
  • os popen method
  • os system() method
  • threading Thread() method
  • subprocess call() method
  • Subprocess check ou output() method

Shutil Copyfile() method

This method copies the source content to the destination only if the destination is writable. If you do not have write permission, it will cause IOError exception.

It opens the input file for reading and ignores its file type. Next, it doesn't process special files in any different way, and it doesn't copy them as new special files.

The Copyfile() method uses the following low-level function copyfileobj(). It takes file names as parameters, opens them, and passes file handles to copyfileobj(). This method has an optional third parameter that you can use to specify the buffer length. It then opens the file and reads a block of the specified buffer size. However, the default is to read the entire file at one time.

copyfile(source_file, destination_file)

Here are the main points about the copyfile() method.

It copies the source content to the destination file.

If the target file is not writable, the copy operation will cause an IOError exception.

If the source and destination files are the same, it will return SameFileError.

However, if the destination file has a different name before it, the copy will overwrite its contents.

If the target is a directory, which means that this method will not be copied to the directory, Error 13 will occur.

It does not support copying files such as character or block drivers and pipes.

# Python Copy File - Sample Code

from shutil import copyfile
from sys import exit

source = input("Enter source file with full path: ")
target = input("Enter target file with full path: ")

# adding exception handling
try:
   copyfile(source, target)
except IOError as e:
   print("Unable to copy file. %s" % e)
   exit(1)
except:
   print("Unexpected error:", sys.exc_info())
   exit(1)

print("\nFile copy done!\n")

while True:
   print("Do you like to print the file ? (y/n): ")
   check = input()
   if check == 'n':
       break
   elif check == 'y':
       file = open(target, "r")
       print("\nHere follows the file content:\n")
       print(file.read())
       file.close()
       print()
       break
   else:
       Continue

Shutil Copy() method

copyfile(source_file, [destination_file or dest_dir])

The function of the copy() method is similar to the "cp" command in Unix. This means that if the destination is a folder, it will create a new file with the same name (base name) as the source file. In addition, the method synchronizes the permissions of the target file to the source file after copying the contents of the source file.

import os
import shutil

source = 'current/test/test.py'
target = '/prod/new'

assert not os.path.isabs(source)
target = os.path.join(target, os.path.dirname(source))

# create the folders if not already exists
os.makedirs(target)

# adding exception handling
try:
   shutil.copy(source, target)
except IOError as e:
   print("Unable to copy file. %s" % e)
except:
   print("Unexpected error:", sys.exc_info())

copy() vs copyfile() :

copy() can also set permission bits when copying content, while copyfile() only copies data.

If the target is a directory, copy() will copy the file, and copyfile() will fail with Error 13.

Interestingly, the copyfile() method uses the copyfileobj() method in the implementation process, while the copy() method uses the copyfile() and copymode() functions in turn.

In position-3, it is obvious that copyfile() will be faster than copy(), because the latter will have an additional task (permission reserved).

Shutil Copyfileobj() method

This method copies the file to the destination path or file object. If the target is a file object, you need to close it after calling copyfileobj(). It also assumes an optional parameter (buffer size) that you can use to set the buffer length. This is the number of bytes saved in memory during replication. The default size used by the system is 16KB.

from shutil import copyfileobj
status = False
if isinstance(target, string_types):
   target = open(target, 'wb')
   status = True
try:
   copyfileobj(self.stream, target, buffer_size)
finally:
   if status:
       target.close()

Shutil Copy2() method

Although the copy2() method functions like copy(). However, it can obtain the access and modification time added in the metadata when copying the data. Copying the same file will cause a SameFileError exception.

copy() vs copy2() :

copy() can only set permission bits, while copy2() can also use timestamps to update file metadata.

copy() calls copyfile() and copymode() inside the function, while copy2() calls copystat() to replace copymode().

Os Popen() method

from shutil import *
import os 
import time
from os.path import basename

def displayFileStats(filename):
   file_stats = os.stat(basename(filename))
   print('\tMode    :', file_stats.st_mode)
   print('\tCreated :', time.ctime(file_stats.st_ctime))
   print('\tAccessed:', time.ctime(file_stats.st_atime))
   print('\tModified:', time.ctime(file_stats.st_mtime))

os.mkdir('test')

print('SOURCE:')
displayFileStats(__file__)

copy2(__file__, 'testfile')

print('TARGET:')
displayFileStats(os.path.realpath(os.getcwd() + '/test/testfile'))

This method creates a pipeline to send or receive commands. It returns an open file object that connects pipes. You can use it for reading or writing based on the file open mode, such as' r '(default) or' w '.

os.popen(command[, mode[, bufsize]])

mode – it can be 'r' (default) or 'w'

Bufsize – if its value is 0, no buffering occurs. If it is set to 1, line buffering occurs when the file is accessed. If you provide a value greater than 1, the buffer will occur with the specified buffer size. However, for negative values, the default buffer size is used.

For Windows systems:

import os
os.popen('copy 1.txt.py 2.txt.py')

For the Linux system:

import os
os.popen('cp 1.txt.py 2.txt.py')

Os System() method

This is the most common way to run any system command. Using the system() method, you can call any command in the subshell. Internally, this method calls the standard library functions of C language.

This method returns the exit status of the command.

For Windows systems:

import os
os.system('copy 1.txt.py 2.txt.py') 

For the Linux system:

import os
os.system('cp 1.txt.py 2.txt.py')

Using asynchronous thread library to copy files

If you want to copy files asynchronously, use the following method. Here, we use Python's threading module to copy in the background.

When using this method, make sure to use locking to avoid locking. This can happen if your application uses multiple threads to read / write files.

import shutil
from threading import Thread

src="1.txt.py"
dst="3.txt.py"

Thread(target=shutil.copy, args=[src, dst]).start()

Copy files using Subprocess's Call() method

The Subprocess module provides a simple interface to handle subprocesses. It allows us to start a Subprocess, connect to the input / output / error pipeline of the Subprocess, and retrieve the return value.

subprocess module is designed to replace old modules and functions, such as – os.system, os.spawn, os.popen, popen2*

It uses the call() method to call system commands to perform user tasks.

import subprocess

src="1.txt.py"
dst="2.txt.py"
cmd='copy "%s" "%s"' % (src, dst)

status = subprocess.call(cmd, shell=True)

if status != 0:
    if status < 0:
        print("Killed by signal", status)
    else:
        print("Command failed with return code - ", status)
else:
    print('Execution of %s passed!\n' % cmd)

Copy the file using the check'u output() method in subprocess

Using the check u output () method in subprocess, you can run an external command or program and capture its output. It also supports pipelines.

import os, subprocess

src=os.path.realpath(os.getcwd() + "http://cdn.techbeamers.com/1.txt.py")
dst=os.path.realpath(os.getcwd() + "http://cdn.techbeamers.com/2.txt.py")
cmd='copy "%s" "%s"' % (src, dst)

status = subprocess.check_output(['copy', src, dst], shell=True)

print("status: ", status.decode('utf-8'))

Posted by john0117 on Mon, 11 Nov 2019 04:47:47 -0800