11. 組織文件

1. shutil 模塊

shutil(或稱為shell 工具)模塊中包含一些函數(shù),讓你在Python 程序中復制、移動、改名和刪除文件。要使用shutil 
的函數(shù),首先需要import shutil。

1.1 復制文件和文件夾

  調(diào)用shutil.copy(source, destination),將路徑source 處的文件復制到路徑destination處的文件夾(source 和
destination 都是字符串)。如果destination 是一個文件名,它將作為被復制文件的新名字。該函數(shù)返回一個字符串,
表示被復制文件的路徑。
import shutil, os
os.chdir('D:\\')    #os.chdir()改變當前目錄
shutil.copy('D://demo1.txt', 'D:\\Jupyter Notebook\\demo2.txt')
  'D:\\Jupyter Notebook\\demo2.txt'
shutil.copytree('D:\\demopack1', 'D:\\Jupyter Notebook\\demopack2')
  'D:\\Jupyter Notebook\\demopack2'
  第一個shutil.copy()調(diào)用將文件D://demo1.txt復制到文件夾D:\\Jupyter Notebook。返回值是剛剛被復制的文件的路徑。請注意,
因為指定了一個文件夾作為目的地址,原來的文件名demo1.txt 就被用作新復制的文件名。第二個shutil.copy()調(diào)用也
將文件D://demo1.txt 復制到文件夾D:\\Jupyter Notebook,但為新文件提供了一個名字demo2.txt。
  shutil.copy()將復制一個文件,shutil.copytree()將復制整個文件夾,以及它包含的文件夾和文件。調(diào)用
shutil.copytree(source, destination),將路徑source 處的文件夾,包括它的所有文件和子文件夾,復制到路徑
destination 處的文件夾。source 和destination 參數(shù)都是字符串。該函數(shù)返回一個字符串,是新復制的文件夾的路徑。
shutil.copytree('D:\\demopack1', 'D:\\Jupyter Notebook\\demopack2')
  'D:\\Jupyter Notebook\\demopack2'

1.2 文件和文件夾的移動和改名

  調(diào)用shutil.move(source, destination),將路徑source 處的文件夾移動到路徑destination,并返回新位置的絕對路徑
的字符串。
  如果destination 指向一個文件夾,source 文件將移動到destination 中,并保持原來的文件名。
shutil.move('D://demo1.txt', 'D:\\Jupyter Notebook\\demopack2')
  'D:\\Jupyter Notebook\\demopack2\\demo1.txt'
如果目的文件夾中已存在了該文件, 則它會被覆蓋。因為這種方式很容易不小心覆蓋文件, 所以使用move()時應注意。
destination路徑也可以指定一個文件名, source文件被移動并改名.
shutil.move('D://demo1.txt', 'D:\\Jupyter Notebook\\new_demo1.txt')
  'D:\\Jupyter Notebook\\new_demo1.txt'
前面的例子都是目的文件夾已存在的情況,如果目的文件夾不存在的話,move()就會將bacon.txt 改名,變成名為eggs 的文件。
>>> shutil.move('C:\\bacon.txt', 'C:\\eggs')
'C:\\eggs'
  這里,move()在C:\目錄下找不到名為eggs 的文件夾,所以假定destination 指的是一個文件,而非文件夾。所以
bacon.txt 文本文件被改名為eggs(沒有.txt 文件擴展名的文本文件),但這可能不是你所希望的!這可能是程序中
很難發(fā)現(xiàn)的缺陷,因為move()調(diào)用會很開心地做一些事情,但和你所期望的完全不同。這也是在使用move()時要小
心的另一個理由。
  最后,構成目的地的文件夾必須已經(jīng)存在,否則Python 會拋出異常。

1.3 永久刪除文件和文件夾

  利用os 模塊中的函數(shù),可以刪除一個文件或一個空文件夾。但利用shutil 模塊,可以刪除一個文件夾及其所有的內(nèi)容。
? 用os.unlink(path)將刪除path 處的文件。
? 調(diào)用os.rmdir(path)將刪除path 處的文件夾。該文件夾必須為空,其中沒有任何文件和文件夾。
? 調(diào)用shutil.rmtree(path)將刪除path 處的文件夾,它包含的所有文件和文件夾都會被刪除。
  在程序中使用這些函數(shù)時要小心!可以第一次運行程序時,注釋掉這些調(diào)用,并且加上print()調(diào)用,顯示會被刪除
的文件。這樣做是一個好主意。下面有一個Python 程序,本來打算刪除具有.txt 擴展名的文件,但有一處錄入錯誤
,結果導致它刪除了.rxt 文件。
import os
for filename in os.listdir():
    if filename.endswith('.rxt'):
    os.unlink(filename)
如果你有某些重要的文件以.rxt 結尾,它們就會被不小心永久地刪除。作為替代,你應該先運行像這樣的程序:
import os
for filename in os.listdir():
    if filename.endswith('.rxt'):
    #os.unlink(filename)
    print(filename)
  現(xiàn)在os.unlink()調(diào)用被注釋掉,所以Python 會忽略它。作為替代,你會打印出將被刪除的文件名。先運行這個版
本的程序,你就會知道,你不小心告訴程序要刪除.rxt 文件,而不是.txt 文件。
  在確定程序按照你的意圖工作后, 刪除print(filename) 代碼行, 取消os.unlink(filename)代碼行的注釋。然后再次
運行該程序,實際刪除這些文件。

1.4 用send2trash 模塊安全地刪除

  因為Python 內(nèi)建的shutil.rmtree()函數(shù)不可恢復地刪除文件和文件夾,所以用起來可能有危險。刪除文件和文件夾
的更好方法,是使用第三方的send2trash 模塊。
  利用send2trash,比Python 常規(guī)的刪除函數(shù)要安全得多,因為它會將文件夾和文件發(fā)送到計算機的垃圾箱或回收
站,而不是永久刪除它們。如果因程序缺陷而用send2trash 刪除了某些你不想刪除的東西,稍后可以從垃圾箱恢復。

2. 遍歷目錄樹

  假定你希望對某個文件夾中的所有文件改名,包括該文件夾中所有子文件夾中的所有文件。也就是說,你希望遍
歷目錄樹,處理遇到的每個文件。寫程序完成這件事,可能需要一些技巧。好在,Python 提供了一個函數(shù),替你
處理這個過程。
for folderName, subfolders, filenames in os.walk('D:\pywork\TXyiqing'):
    print('The current folder is ' + folderName)
    for subfolder in subfolders:
        print('SUBFOLDER OF ' + folderName + ': ' + subfolder)
    for filename in filenames:
        print('FILE INSIDE ' + folderName + ': ' + filename)
print(' ')
The current folder is D:\pywork\TXyiqing
SUBFOLDER OF D:\pywork\TXyiqing: .idea
SUBFOLDER OF D:\pywork\TXyiqing: Include
SUBFOLDER OF D:\pywork\TXyiqing: Lib
SUBFOLDER OF D:\pywork\TXyiqing: Scripts
FILE INSIDE D:\pywork\TXyiqing: pyvenv.cfg
FILE INSIDE D:\pywork\TXyiqing: spider.py
FILE INSIDE D:\pywork\TXyiqing: SQLdb.py
The current folder is D:\pywork\TXyiqing\.idea
SUBFOLDER OF D:\pywork\TXyiqing\.idea: dictionaries
SUBFOLDER OF D:\pywork\TXyiqing\.idea: inspectionProfiles
FILE INSIDE D:\pywork\TXyiqing\.idea: misc.xml
FILE INSIDE D:\pywork\TXyiqing\.idea: modules.xml
FILE INSIDE D:\pywork\TXyiqing\.idea: TXyiqing.iml
FILE INSIDE D:\pywork\TXyiqing\.idea: workspace.xml
The current folder is D:\pywork\TXyiqing\.idea\dictionaries
FILE INSIDE D:\pywork\TXyiqing\.idea\dictionaries: ChaosA.xml
The current folder is D:\pywork\TXyiqing\.idea\inspectionProfiles
FILE INSIDE D:\pywork\TXyiqing\.idea\inspectionProfiles: Project_Default.xml
os.walk()函數(shù)被傳入一個字符串值,即一個文件夾的路徑。你可以在一個for
循環(huán)語句中使用os.walk()函數(shù),遍歷目錄樹,就像使用range()函數(shù)遍歷一個范圍的
數(shù)字一樣。不像range(),os.walk()在循環(huán)的每次迭代中,返回3 個值:
1.當前文件夾名稱的字符串。
2.當前文件夾中子文件夾的字符串的列表。
3.當前文件夾中文件的字符串的列表。
所謂當前文件夾,是指for 循環(huán)當前迭代的文件夾。程序的當前工作目錄,不會因為os.walk()而改變。就像你可以
在代碼for i in range(10):中選擇變量名稱i 一樣,你也可以選擇前面列出來的3 個字的變量名稱。我通常使用
foldername、subfolders 和filenames。

3. 用zipfile 模塊壓縮文件

3.1 讀取ZIP文件

  要讀取ZIP 文件的內(nèi)容,首先必須創(chuàng)建一個ZipFile 對象(請注意大寫首字母Z和F)。ZipFile 對象在概念上與File 
對象相似,你在第8 章中曾經(jīng)看到open()函數(shù)返回File 對象:它們是一些值,程序通過它們與文件打交道。要創(chuàng)建
一個ZipFile對象,就調(diào)用zipfile.ZipFile()函數(shù),向它傳入一個字符串,表示.zip 文件的文件名。
請注意,zipfile 是Python 模塊的名稱,ZipFile()是函數(shù)的名稱。
import zipfile, os
os.chdir('D:\\')
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.namelist()
  ['cats/catnames.txt', 'cats/zophie.jpg', 'spam.txt', 'cats/']
spamInfo = exampleZip.getinfo('spam.txt')
spamInfo.file_size
  0
spamInfo.compress_size
  0
  ZipFile 對象有一個namelist()方法,返回ZIP 文件中包含的所有文件和文件夾的字符串的列表。這些字符串可以傳
遞給ZipFile 對象的getinfo()方法,返回一個關于特定文件的ZipInfo 對象。ZipInfo 對象有自己的屬性,諸如表示字
節(jié)數(shù)的file_size和compress_size,它們分別表示原來文件大小和壓縮后文件大小。ZipFile 對象表示整個歸檔文
件,而ZipInfo 對象則保存該歸檔文件中每個文件的有用信息。

3.2 從ZIP中解壓縮

ZipFile 對象的extractall()方法從ZIP 文件中解壓縮所有文件和文件夾,放到當前工作目錄中。
import zipfile, os
os.chdir('D:\\')
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extractall()
exampleZip.close()
  運行這段代碼后, example.zip的內(nèi)容被解壓到D:\。或者,你可以想extractall()傳遞一個文件夾名稱, 它將解壓
縮到那個文件夾,而不是當前工作目錄。如果傳遞給extractall()方法的文件夾不存在, 它會被創(chuàng)建。
ZipFile對象的extract()方法從ZIP文件中解壓縮單個文件
import zipfile, os
os.chdir('D:\\')
exampleZip = zipfile.ZipFile('example.zip')
exampleZip.extract('spam.txt')
  'D:\\spam.txt'
exampleZip.extract('spam.txt', 'D:\Jupyter Notebook')
  'D:\\Jupyter Notebook\\spam.txt'
exampleZip.close()
傳遞給extract()的字符串,必須匹配namelist()返回的字符串列表中的一個?;蛘?,你可以向extract()傳遞第二個參
數(shù),將文件解壓縮到指定的文件夾,而不是當前工作目錄。如果第二個參數(shù)指定的文件夾不存在,Python 就會創(chuàng)
建它。extract()的返回值是被壓縮后文件的絕對路徑。

3.3 創(chuàng)建和添加ZIP文件

  要創(chuàng)建你自己的壓縮ZIP 文件,必須以“寫模式”打開ZipFile 對象,即傳入'w'作為第二個參數(shù)(這類似于向open()
函數(shù)傳入'w',以寫模式打開一個文本文件)。如果向ZipFile 對象的write()方法傳入一個路徑,Python 就會壓縮該
路徑所指的文件,將它加到ZIP 文件中。write()方法的第一個參數(shù)是一個字符串,代表要添加的文件名。第二個參
數(shù)是“壓縮類型”參數(shù),它告訴計算機使用怎樣的算法來壓縮文件??梢钥偸菍⑦@個值設置為    
zipfile.ZIP_DEFLATED(這指定了deflate 壓縮算法,它對各種類型的數(shù)據(jù)都很有效)
newZip = zipfile.ZipFile('new.zip', 'w')
newZip.write('spam.txt', compress_type = zipfile.ZIP_DEFLATED)
newZip.close()
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容