用Python複製文件的9個方法

Python 中有許多「開蓋即食」的模塊(好比 os,subprocess 和 shutil)以支持文件 I/O 操做。在這篇文章中,你將會看到一些用 Python 實現文件複製的特殊方法。下面咱們開始學習這九種不一樣的方法來實現 Python 複製文件操做。python

在開始以前,你必須明白爲何瞭解最適合你的 Python 複製文件方法是如此重要。這是由於文件 I/O 操做屬於性能密集型並且常常會達到瓶頸。這就是爲何你應該根據你的應用程序的設計選擇最好的方法。shell

一些共享資源的程序會傾向於以阻塞模式來複制文件,而有些則可能但願以異步方式執行。好比 — 使用線程來複制文件或者啓動單獨的進程來實現它。還有一點須要考慮的是平臺的可移植性。這意味着你應該知道你要運行的程序所在的目標操做系統(Windows/Linux/Mac OS X 等)。異步

用 Python 複製文件的 9 種方法具體是:函數

  • shutil copyfile() 方法
  • shutil copy() 方法
  • shutil copyfileobj() 方法
  • shutil copy2() 方法
  • os popen 方法
  • os system() 方法
  • threading Thread() 方法
  • subprocess call() 方法
  • subprocess check_output() 方法

Shutil Copyfile()方法性能

只有當目標是可寫的,這個方法纔會將源內容複製到目標位置。若是你沒有寫入權限,則會致使 IOError 異常。學習

它會打開輸入文件進行讀取並忽略其文件類型。接下來,它不會以任何不一樣的方式處理特殊文件,也不會將它們複製爲新的特殊文件。spa

Copyfile() 方法使用下面的低級函數 copyfileobj()。它將文件名做爲參數,打開它們並將文件句柄傳遞給 copyfileobj()。這個方法中有一個可選的第三個參數,你可用它來指定緩衝區長度。而後它會打開文件並讀取指定緩衝區大小的塊。可是,默認是一次讀取整個文件。操作系統

copyfile(source_file, destination_file)

如下是關於 copyfile() 方法的要點。線程

它將源內容複製到目標文件中。設計

若是目標文件不可寫入,那麼複製操做將致使 IOError 異常。

若是源文件和目標文件都相同,它將會返回 SameFileError。

可是,若是目標文件以前有不一樣的名稱,那麼該副本將會覆蓋其內容。

若是目標是一個目錄,這意味着此方法不會複製到目錄,那麼會發生 Error 13。

它不支持複製諸如字符或塊驅動以及管道等文件。

# 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()方法

copyfile(source_file, [destination_file or dest_dir])

copy() 方法的功能相似於 Unix 中的「cp」命令。這意味着若是目標是一個文件夾,那麼它將在其中建立一個與源文件具備相同名稱(基本名稱)的新文件。此外,該方法會在複製源文件的內容後同步目標文件權限到源文件。

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() 還能夠在複製內容時設置權限位,而 copyfile() 只複製數據。

若是目標是目錄,則 copy() 將複製文件,而 copyfile() 會失敗,出現 Error 13。

有趣的是,copyfile() 方法在實現過程當中使用 copyfileobj() 方法,而 copy() 方法則是依次使用 copyfile() 和 copymode() 函數。

在 Potion-3 能夠很明顯看出 copyfile() 會比 copy() 快一點,由於後者會有一個附加任務(保留權限)。

Shutil Copyfileobj()方法

該方法將文件複製到目標路徑或者文件對象。若是目標是文件對象,那麼你須要在調用 copyfileobj() 以後關閉它。它還假定了一個可選參數(緩衝區大小),你能夠用來設置緩衝區長度。這是複製過程當中保存在內存中的字節數。系統使用的默認大小是 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()方法

雖然 copy2() 方法的功能相似於 copy()。可是它能夠在複製數據時獲取元數據中添加的訪問和修改時間。複製相同的文件會致使 SameFileError 異常。

copy() vs copy2() :

copy() 只能設置權限位,而 copy2() 還可使用時間戳來更新文件元數據。

copy() 在函數內部調用 copyfile() 和 copymode(), 而 copy2() 是調用 copystat() 來替換copymode()。

Os Popen()方法

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'))

該方法建立一個發送或者接受命令的管道。它返回一個打開的而且鏈接管道的文件對象。你能夠根據文件打開模式將其用於讀取或者寫入好比‘r’(默認)或者‘w’。

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

mode – 它能夠是‘r’(默認)或者‘w’

Bufsize – 若是它的值是0,那麼就不會出現緩衝。若是將它設置爲1,那麼在訪問文件時就會發生行緩衝。若是你提供一個大於1的值,那麼就會在指定緩衝區大小的狀況下發生緩衝。可是,對於負值,系統將採用默認緩衝區大小。

對於Windows系統:

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

對於Liunx系統:

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

Os System()方法

這是運行任何系統命令的最經常使用方式。使用 system() 方法,你能夠調用 subshell 中的任何命令。在內部,該方法將調用 C 語言的標準庫函數。

該方法返回該命令的退出狀態。

對於 Windows 系統:

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

對於 Liunx 系統:

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

使用異步方式的線程庫複製文件

若是你想以異步方式複製文件,那麼使用下面的方法。在這裏,咱們使用 Python 的線程模塊在後臺進行復制操做。

在使用這種方法時,請確保使用鎖定以免鎖死。若是你的應用程序使用多個線程讀取/寫入文件,就可能會遇到這種狀況。

import shutil
from threading import Thread

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

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

使用Subprocess的Call()方法複製文件

Subprocess 模塊提供了一個簡單的接口來處理子進程。它讓咱們可以啓動子進程,鏈接到子進程的輸入/輸出/錯誤管道,並檢索返回值。

subprocess 模塊旨在替換舊版模塊和函數,好比 – os.system, os.spawn, os.popen, popen2.*

它使用 call() 方法調用系統命令來執行用戶任務。

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)

使用 subprocess 中的 Check_output() 方法複製文件

使用 subprocess 中的 Check_output() 方法,你能夠運行外部命令或程序並捕獲其輸出。它也支持管道。

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'))
相關文章
相關標籤/搜索