整合 Python標準庫之 Path/File 類

浮生若夢的程式設計發表於2019-02-26

起因

os/os.path/shutil 中的一些介面,經常讓我迷惑,一會在這個庫中,一會在那個庫,有時候貌似同一個功能有好幾個介面,比如 copy/copyfile/copyfileobj;remove file 的介面貌似在 os 中, remove dir 的介面又在 shutil 中,經常讓人傻傻分不清楚。

再加上年紀越大,記效能力就呈現出一種可感知的衰減,越記東西就越記不住,反覆記憶也沒用,不免讓人感到哀傷。

使用 Java 貌似就沒有這麼多糾結,介面都很符合直覺,幾乎沒有記憶過API,每次都是 IDE 自動補全(用到比較少的介面,根據 IDE 的彈窗也能臨時選對,不用深入原始碼或文件)。

把這些雜七雜八的介面再做一層簡單包裝,就是一種很自然的動力,本文著眼於此,致力於減少這種心智負擔,儘可能對上提供一致的 API 。

包裝

這幾個標準庫的文件很好懂,並沒有什麼值得討論的地方(可惜就是老記不住 :)),參照 Java 中對應類的API,我們的包裝工作也是易如反掌。

如下:

import os
import shutil


class Path:
    def __init__(self, pathstr: str):
        self._pathstr = pathstr
        self._abspath = os.path.abspath(pathstr)

    def get_parent(self):
        return Path(os.path.dirname(self._abspath))

    def get_childs(self):
        return [Path(c)
                for c in os.listdir(self._abspath)]

    def is_absolute(self):
        return os.path.isabs(self._pathstr)

    def is_dir(self):
        return os.path.isdir(self._abspath)

    def is_file(self):
        return os.path.isfile(self._abspath)

    def join(self, s):
        return Path(os.path.join(self._abspath, s))

    def get_basename(self):
        return os.path.basename(self._abspath)

    def get_extension(self):
        return os.path.splitext(self._abspath)[1]

    def get_filename(self):
        return os.path.split(self._abspath)[1]

    def is_exists(self):
        return os.path.exists(self._abspath)

    def ends_with(self, ext):
        return self._abspath.endswith(ext)

    def touch(self):
        if self.is_exists():
            return True

        open(self._abspath, mode=`r`, encoding=`utf-8`).close()

        return True

    def mkdir(self):
        if self.is_exists():
            return

        os.makedirs(self._abspath)

        return True

    def rm(self):
        if not self.is_exists():
            return

        if self.is_file():
            os.remove(self._abspath)
        if self.is_dir():
            shutil.rmtree(self._abspath)

    def mv(self, dest):
        shutil.move(self._abspath, dest)

    def cp(self, dest):
        if self.is_file():
            shutil.copyfile(self._abspath, dest)

        if self.is_dir():
            shutil.copytree(self._abspath, dest)


class File:
    def __init__(self, filestr: str):
        if not os.path.isfile(filestr):
            raise ValueError(`must be a real file, now is %s` % filestr)

        self._filestr = os.path.abspath(filestr)
        self._statresult = os.stat(self._filestr)

    def get_size(self):
        return self._statresult.st_size

    def get_create_time(self):
        return self._statresult.st_ctime
複製程式碼

使用如下:

Path(`/root/newfile`).touch()
Path(`/root/newdir`).mkdir()
複製程式碼

不妨將其放到專案的 utils/ 下面,這樣就再也不用記憶那一堆亂糟糟的 API 了。:)

好處

其實,Python 標準庫的很多 API,直接使用時,總是需要臨時查查文件,或是反覆記憶,使用頻率很高也都要查閱文件(感覺是 API設計不佳),不免讓人小煩惱。這個時候,做一層簡單的包裝或轉發,可以立刻減少這種痛苦

相關文章