Python级作为服务

时间:2013-05-28 07:47:23

标签: python architecture

将被视为服务的类的优秀设计是什么:它从磁盘上的大数据初始化,然后响应来自另一个模块的请求?

可以只使用静态数据吗?通过调用Init函数从磁盘加载数据,之后可以请求该类。

请你批评这个解决方案吗?你会建议更好的东西吗?

1 个答案:

答案 0 :(得分:2)

从您的描述中我了解到您建议将所有数据从磁盘读取到类实例或类似的成员(如果这是您正在计划的话,我不会使用模块全局变量)然后使用该数据响应请求数据 - 我理解正确吗?

只要系统上有足够的内存,这种方法就能正常工作 - 因为我不知道你的数据有多大,我无法评论这是否真实。但是,您对代码施加了可伸缩性限制,因此如果数据变得越来越大,那么您可能会因代码运行速度非常慢或导致崩溃而面临风险。不同的平台对内存耗尽的反应略有不同,但结果几乎总是不合适。

在可能的情况下,最好从磁盘上按需读取数据,如果合适,可能还需要一些内存中缓存。如果可以的话,我建议将数据放入结构化格式,SQLite之类的东西是创建结构化文件数据的一种相当简单的方法。然后,您可以编写执行SQL查询的方法,以根据需要从文件中恢复数据。

如果你需要通过在内存中缓存常见结果来获得更好的性能,你可以在你要缓存的所有函数周围使用类似Python 3的LRU cache装饰器。这假设函数的结果仅取决于其参数。如果您使用的是Python 2.x,那么您可以找到implementations for that too,但不在标准库中。

如果您的结果依赖于类成员和函数参数,您可能需要做一些额外的工作,可以通过编写自己的缓存层,也可以使用上述解决方案,并在适当的类成员手动清除缓存更改。我不能在不了解你的问题的情况下给你详细说明,但希望能涵盖所涉及的问题。

这是回答你的问题,还是我错过了这一点?如果您需要不同的答案,请提供说明。

修改

在下面发表评论之后,我想我会补充一点澄清。

首先,我并不完全确定“静态”数据的含义 - Python并不像C / C ++或Java那样真正拥有这个概念。您可以拥有类属性,它们存储在类对象中,可供实例使用,就好像它们是常规属性一样:

class MyClass(object):

    class_attribute = 123

    def method(self):
        print "Class attribute value: %d" % (self.class_attribute,)

......但在这种情况下,我认为这不是一个好主意。也许通过“静态”,你只是将一堆数据存储为类实例的属性,如果是这样,那对你所描述的内容来说似乎是一个非常明智的选择。

所以你的类最终会得到一个__init__()方法,它可能会把文件名作为一个参数(即使你现在修复存储数据的文件,它可能不会在将来,加上使用不同的单元测试可能是有用的)。然后,此方法将导致数据被加载并存储为实例属性。我建议将实际加载委托给另一个方法,这样就可以重新加载数据而无需构建新实例。

举一个简单的例子,如果你的类正在存储文件中的行,那么你可能会:

class FileLines(object):

    def __init__(self, filename):
        self.lines = []
        self.load_file(filename)

    def load_file(self, filename):
        with open(filename, "r") as fd:
            self.lines = [i.rstrip() for i in fd]

(我发现在lines中设置__init__()并非严格要求,因为它已在load_file()中重置,但我认为最好在__init__()中初始化所有属性)。

这显然是一个非常毫无意义的课程,但你明白了 - 从__init__()读取数据然后使其可用。顺便说一句,我故意没有为lines属性添加“getter”方法 - 在Python中直接访问属性是完全可以接受的,不需要你经常在C中看到的“getter”和“setter”方法/ C ++和Java。这是因为如果需要实现更复杂的功能,可以在Python中使用properties来使用方法替换简单属性。因此,您现在可以灵活地使用基本属性的简单性,以便以后使用。

另外,假设您的数据具有结构,您应该考虑如何存储它。字典,列表和集合在Python中都非常强大,但如果您的数据有命名字段,那么请考虑使用collections.namedtuple或自定义类来表示它。这使得类的用户访问它更方便(因此更不容易出错)。理想情况下,我建议尝试将对象的内存中表示保留在一个类中,并使代码在其他地方解析磁盘表示,从而生成内存中版本的实例。以这种方式保持表示分离将允许您将类的用户与磁盘表示中的更改隔离。

希望这有所帮助。