如何构建Python模块?

时间:2016-10-08 17:06:33

标签: python

这是我第一次发布堆栈溢出,所以如果我做错了,我会道歉。

我试图了解构建Python模块的最佳方法。作为一个例子,我制作了一个同步源和目标的备份模块,只有在源和目标之间存在差异时才复制文件。备份模块仅包含名为Backup的类。

现在我被告知OOP是有史以来最伟大的事情,但这似乎是错误的。在查看了一些标准库源代码之后,我发现大多数内容都没有分成一个类。我试图对此做一些研究,以确定何时应该使用一个类,何时我应该只有函数,并且我得到了不同的信息。我想我的主要问题是,如果下面的代码留作一个类,或者它应该只是一个带有函数的模块。目前非常简单,但我可能希望将来增加更多。

"""Class that represents a backup event."""

import hashlib
import os
import shutil

class Backup:
    def __init__(self, source, destination):
        self.source = source
        self.destination = destination

    def sync(self):
        """Synchronizes root of source and destination paths."""

        sroot = os.path.normpath(self.source)
        droot = os.path.normpath(self.destination) + '/' + os.path.basename(sroot)

        if os.path.isdir(sroot) and os.path.isdir(droot):
            Backup.sync_helper(sroot, droot)
        elif os.path.isfile(sroot) and os.path.isfile(droot):
            if not Backup.compare(sroot, droot):
                Backup.copy(sroot, droot)
        else:
            Backup.copy(sroot, droot)

    def sync_helper(source, destination):
        """Synchronizes source and destination."""

        slist = os.listdir(source)
        dlist = os.listdir(destination)

        for s in slist:
            scurr = source + '/' + s
            dcurr = destination + '/' + s

            if os.path.isdir(scurr) and os.path.isdir(dcurr):
                Backup.sync_helper(scurr, dcurr)
            elif os.path.isfile(scurr) and os.path.isfile(dcurr):
                if not Backup.compare(scurr, dcurr):
                    Backup.copy(scurr, dcurr)
            else:
                Backup.copy(scurr, dcurr)

        for d in dlist:
            if d not in slist:
                Backup.remove(destination + '/' + d)

    def copy(source, destination):
        """Copies source file, directory, or symlink to destination"""

        if os.path.isdir(source):
            shutil.copytree(source, destination, symlinks=True)
        else:
            shutil.copy2(source, destination)

    def remove(path):
        """Removes file, directory, or symlink located at path"""

        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.unlink(path)

    def compare(source, destination):
        """Compares the SHA512 hash of source and destination."""

        blocksize = 65536
        shasher = hashlib.sha512()
        dhasher = hashlib.sha512()

        while open(source, 'rb') as sfile:
            buf = sfile.read(blocksize)
            while len(buf) > 0:
                shasher.update(buf)
                buf = sfile.read(blocksize)

        while open(destination, 'rb') as dfile:
            buf = dfile.read(blocksize)
            while len(buf) > 0:
                dhasher.update(buf)
                buf = dfile.read(blocksize)

        if shasher.digest() == dhasher.digest():
            return True
        else:
            return False

我认为它作为一个类没有意义,因为唯一的方法是同步。另一方面,备份是真实世界的对象。这真让我困惑。

作为一些方面的问题。我的同步方法和sync_helper函数看起来非常相似,可能有可能以某种方式将两者合并(我将其留作自己的练习),但这通常是如何在使用需要某个初始状态的递归函数时完成的。意思是,可以在一个函数中执行某些操作以达到某个状态,然后调用执行实际操作的递归函数。这看起来很乱。

最后,我有一堆实用程序函数,它们实际上不是对象的一部分,但是由sync使用。将这些分解为像实用程序子模块或不引起混淆的事情会更有意义吗?

构建我的程序对我来说是最令人困惑的事情,任何帮助都会非常感激。

1 个答案:

答案 0 :(得分:0)

这种方法(以及其他几种方法)是错误的:

def copy(source, destination):
    """Copies source file, directory, or symlink to destination"""

它的工作方式(Backup.copy(scurr, dcurr)),但在实例上使用时不起作用。

Python中的所有方法都应该将self作为第一个位置参数:def copy(self, source, destination),或者应该转换为staticmethod(或移出类)。

使用staticmethod装饰器声明静态方法:

@staticmethod
def copy(source, destination):
    """Copies source file, directory, or symlink to destination"""

但在这种情况下,sourcedestination实际上是Backup个实例的属性,因此可能应修改它以使用属性:

def copy(self):
    # use self.source and self.destination