1. 程式人生 > Python進階應用教學 >24 Python 基礎實戰

24 Python 基礎實戰

1. 概述

本節實現一個檔案管理程式,該程式會使用到如下知識點:

  • 函式
  • 面向物件
    • 採用面向物件的程式設計方法對資料建模
  • 異常處理
    • 使用異常處理和檔案相關的錯誤,例如檔案不存在
  • 模組
    • 程式由多個原始檔構成,每個原始檔實現一個功能模組
  • os 模組
    • 需要使用 os 模組提供的方法
  • sys 模組
    • 需要使用 os 模組提供的方法
  • 檔案訪問

2. 程式功能

2.1 概述

檔案管理程式提供瞭如下功能:

  • 列出目錄下的檔名
  • 列印檔案內容
  • 複製檔案
  • 刪除檔案

檔案管理程式是一個命令列程式,讀取使用者輸入命令,然後執行返回命令執行結果。檔案管理程式支援如下命令:

命令 功能
ls dir 列出目錄 dir 下的檔案
cat file 列印檔案 file 的內容
cp src dst 複製原始檔 src 到目標檔案 dst
rm file 刪除檔案 file
exit 退出程式

2.2 測試檔案 test.txt

本節需要使用一個用於測試的文字檔案 test.txt,內容如下:

www
imooc
com

2.3 示例

下面的命令演示了檔案管理程式的用法:

2.3.1 啟動程式

C:\> python main.py
> 
  • 在第 1 行,程式的主檔案是 main.py,啟動程式
  • 在第 2 行,程式啟動後,列印提示符 >,等待使用者輸入命令

2.3.2 輸入命令 help

> help
exit          - exit program
cat file      - print file
ls            - list file in current dir
ls dir        - list file in dir
cp src dst    - copy file
rm file       - remove file
  • 在第 1 行,輸入命令 help,功能是列印各個命令的用法

2.3.3 輸入命令 cat

> cat test.txt
www
imooc
com
  • 在第 1 行,輸入命令 cat test.txt,功能是列印檔案 test.txt 的內容

2.3.4 輸入命令 ls

> ls
main.py
test.txt
  • 在第 1 行,輸入命令 ls,功能是列出當前目錄下的檔案
> ls C:\
Documents and Settings
Program Files
Program Files (x86)
ProgramData
System Volume Information
Users
Windows
  • 在第 1 行,輸入命令 ls C:\,功能是列出 C 盤根目錄下的檔案

2.3.5 輸入命令 cp

> cp test.txt test.bak
> ls
main.py
test.txt
test.bak
  • 在第 1 行,輸入命令 cp test.txt test.bak,功能是將檔案 test.txt 複製到 test.bak
  • 在第 2 行,輸入命令 ls,列出當前目錄下的檔案,發現新增了一個檔案 test.bak

2.3.6 輸入命令 rm

> rm test.bak
> ls
main.py
test.txt
  • 在第 1 行,輸入命令 rm test.bak,功能是刪除檔案 test.bak
  • 在第 2 行,輸入命令 ls,列出當前目錄下的檔案,發現檔案 test.bak 被刪除了

2.3.6 輸入命令 exit

> exit
C:\>
  • 在第 1 行,輸入命令 exit,功能是退出程式
  • 在第 2 行,返回到 DOS 命令列模式

2.4 錯誤處理

檔案管理程式提供了錯誤處理功能,如果執行某條命令時發生了錯誤,例如檔案不存在,僅僅終止該命令,而不是終止程式。

> cat non-exist-file
[Errno 2] No such file or directory: 'non-exisit-file'
>
  • 在第 1 行,列印檔案 non-exist-file,該檔案並不存在,cat 命令執行會出錯
  • 在第 2 行,cat 命令執行中止,列印錯誤提示資訊
  • 在第 3 行,cat 命令中止後,列印命令提示符,等待使用者輸入新的命令

3. 程式框架

檔案管理程式由多個原始檔構成,它們的功能如下:

原始檔 功能
main.py 主控程式,讀取使用者的命令並執行
command.py 定義類 Command,定義了命令的介面
help.py 定義類 HelpCommand,實現 help 命令的功能
ls.py 定義類 LsCommand,實現 ls 命令的功能
cat.py 定義類 CatCommand,實現 cat 命令的功能
cp.py 定義類 CpCommand,實現 cp 命令的功能
rm.py 定義類 RmCommand,實現 rm 命令的功能

4. 實現主控程式

編寫檔案 main.py,讀取使用者的命令並執行:

import sys
import cat
import ls
import cp
import rm
import help
  • 在第 1 行匯入 Python 內建的 sys 模組
  • 在第 2 行到第 6 行匯入使用者自定義的 5 個模組
    • cat 模組中定義了類 CatCommand,實現 cat 命令的功能
    • ls 模組中定義了類 LsCommand,實現 ls 命令的功能
    • cp 模組中定義了類 CpCommand,實現 cp 命令的功能
    • rm 模組中定義了類 RmCommand,實現 rm 命令的功能
    • help 模組中定義了類 HelpCommand,實現 help 命令的功能
def readAndExecute():
    print('> ', end = '')
    line = input()
    args = line.split()
    if len(args) == 0:
        return
  • 在第 1 行,定義函式 readAndExecute(), 讀取使用者輸入的命令並執行
  • 在第 2 行,列印提示符 >
  • 在第 3 行,讀取使用者輸入的命令
  • 在第 4 行,將使用者輸入的命令分割為多個單詞
    • 假設使用者輸入命令是 cp test.txt test.bak
    • 經過 split() 後,args = [‘cp’, ‘test.txt’, ‘test.bak’]
    arg0 = args[0]
    if arg0 == 'exit':
        sys.exit()
    elif arg0 == 'cat':
        command = cat.CatCommand(args)
    elif arg0 == 'ls':
        command = ls.LsCommand(args)
    elif arg0 == 'cp':
        command = cp.CpCommand(args)
    elif arg0 == 'rm':
        command = rm.RmCommand(args)
    else:
        command = help.HelpCommand(args)

    command.execute()
  • 第 0 個引數是命令的名稱,根據命令的名稱構造相應的命令物件
    • 如果命令是 exit,呼叫 sys 模組的 exit 方法退出程式
    • 如果命令是 cat,使用 cat 模組中定義的類 CatCommand 例項化一個命令物件
    • 如果命令是 ls,使用 ls 模組中定義的類 LsCommand 例項化一個命令物件
    • 如果命令是 cp,使用 cp 模組中定義的類 CpCommand 例項化一個命令物件
    • 如果命令是 rm,使用 rm 模組中定義的類 RmCommand 例項化一個命令物件
    • 如果不是以上命令,使用 help 模組中定義的類 HelpCommand 例項化一個命令物件
  • 在最後,呼叫命令物件 command 的 execute 方法執行命令
while True:
    try:
        readAndExecute()
    except IOError as error:
        print(error)
  • 在第 1 行,定義迴圈,迴圈反覆執行函式 readAndExecute()
  • 執行函式 readAndExecute 時,可能會出現 IOError
    • 在 try 語句中執行 readAndExecute
    • 使用 except 語句捕獲執行過程中的 IOError,並列印 error
  • 注意,當 readAndExecute 出現異常時,僅僅終止 readAndExecute,而不是終止程式

5. 實現命令介面

編寫檔案 command.py 實現命令的介面:

class Command:
    def __init__(self, args):
        self.args = args

    def execute(self):
        print('Command.execute')
  • 在第 1 行,定義類 Command,描述了一個命令的介面
    • __init__ 方法,使用引數陣列 args 構造一個命令
    • execute 方法,執行命令的功能,這裡只提供了一個介面
  • 具體的命令如 LsCommand 繼承類 Command,實現 execute 方法

6. 實現 help 命令

編寫檔案 help.py 實現 help 命令:

from command import Command

class HelpCommand(Command):
    def __init__(self, args):
        Command.__init__(self, args)

    def execute(self):
        print('exit          - exit program')
        print('cat file      - print file')
        print('ls            - list file in current dir')
        print('ls dir        - list file in dir')
        print('cp src dst    - copy file')
        print('rm file       - remove file')       
  • 在第 1 行,從 command 模組中匯入類 Command
  • 在第 3 行,定義類 HelpCommand,繼承於類 Command
  • 在第 5 行,呼叫父類的建構函式
  • 在第 7 行,定義 execute 方法,列印各個命令的功能

7. 實現 ls 命令

編寫檔案ls.py 實現 ls 命令:

from command import Command
import os

class LsCommand(Command):
    def __init__(self, args):
        Command.__init__(self, args)

    def usage(self):
        print('ls            - list file in current dir')
        print('ls dir        - list file in dir')
  • 在第 1 行,從 command 模組中匯入類 Command
  • 在第 3 行,定義類 HelpCommand,繼承於類 Command
  • 在第 5 行,呼叫父類的建構函式
  • 在第 7 行,定義方法 usage 列印 ls 命令的功能
    def execute(self):
        if len(self.args) == 1:
            path = '.'
        elif len(self.args) == 2:
            path = self.args[1]
        else:
            self.usage()
            return
  • 如果執行的命令是 ls,則設定 path 為 ‘.’,列出當前目錄下的檔案
  • 如果執行的命令是 ls dir,則設定 path 為 args[1],列出指定目錄下的檔案
        entries = os.listdir(path)
        for entry in entries:
            print(entry)
  • 呼叫 os 模組的 listdir 方法,列出目錄 path 下的檔案

8. 實現 cat 命令

編寫檔案 cat.py,定義類 CatCommand 用於實現 cat 命令的功能:

from command import Command

class CatCommand(Command):
    def __init__(self, args):
        Command.__init__(self, args)

    def usage(self):
        print('cat file      - print file')
  • 在第 1 行,從 command 模組中匯入類 Command
  • 在第 3 行,定義類 HelpCommand,繼承於類 Command
  • 在第 5 行,呼叫父類的建構函式
  • 在第 7 行,定義方法 usage 列印 cat 命令的功能
    def execute(self):
        if len(self.args) != 2:
            self.usage()
            return

        path = self.args[1]
  • 如果命令為 cat file,則設定 path 為 args[1]
        file = open(path)
        for line in file:
            print(line, end = '')
        file.close() 
  • 使用 for 迴圈遍歷檔案的每一行,並輸出

9. 實現 cp 命令

編寫檔案 cp.py,定義類 CpCommand 用於實現 cp 命令的功能

from command import Command

class CpCommand(Command):
    def __init__(self, args):
        Command.__init__(self, args)

    def usage(self):
        print('cp src dst    - copy file')
  • 在第 1 行,從 command 模組中匯入類 Command
  • 在第 3 行,定義類 CpCommand,繼承於類 Command
  • 在第 5 行,呼叫父類的建構函式
  • 在第 7 行,定義方法 usage 列印 cp 命令的功能
    def execute(self):
        if len(self.args) != 3:
            self.usage()
            return

        src_path = self.args[1]
        dst_path = self.args[2]
  • 設定 src_path 為 args[1]
  • 設定 dst_path 為 args[2]
        src_file = open(src_path, 'r')
        dst_file = open(dst_path, 'w')
        for line in src_file:
            dst_file.write(line)
        src_file.close()
        dst_file.close()
  • 以只讀方式開啟 src_path,以只寫方式開啟 dst_path
  • 遍歷原始檔 src_file 的每一行,將其寫入到 dst_file 中

10. 實現 rm 命令

編寫檔案 rm.py,定義類 RmCommand 用於實現 rm 命令的功能

from command import Command
import os

class RmCommand(Command):
    def __init__(self, args):
        Command.__init__(self, args)

    def usage(self):
        print('rm file       - remove file')
  • 在第 1 行,從 command 模組中匯入類 Command
  • 在第 3 行,定義類 RmCommand,繼承於類 Command
  • 在第 5 行,呼叫父類的建構函式
  • 在第 7 行,定義方法 usage 列印 rm 命令的功能
    def execute(self):
        if len(self.args) != 2:
            self.usage()
            return

        path = self.args[1]
        os.remove(path)
  • 呼叫 os 模組的 remove 方法刪除檔案