如何使用户配置可用于模块的所有类

时间:2014-12-02 14:52:35

标签: python

我正在编写一个Python库,用作第三方库。

great_library/__init__.py

class ClassA(object):

    @cache()
    def foo(self):
        pass

class ClassB(object):

    @cache()
    def bar(self):
        pass

class GreatLibrary(object):

    @classmethod        
    def great_api(cls):
        pass

    # uses ClassA and ClassB

此库用作:

from great_library import GreatLibrary
GreatLibrary.great_api()

现在的问题是,我希望用户配置缓存过期时间。应该传递给@cache()@cache(seconds)

我应该如何设计这个模块结构,以便用户可以轻松传入配置并让它由classA和classB使用?感谢

1 个答案:

答案 0 :(得分:1)

基本问题是当加载模块时,将读取传递给装饰器的变量。所以之前没有办法改变它(至少如果你不想通过一些黑客重新加载模块但是不能改变旧的对象)。所以你需要一些钩子,其中great_library可以获得缓存时间的值以及用户可以写出所需值的位置。

更简单和广泛使用的方法是设置环境变量。在great_library模块的顶部,您可以检查变量并加载默认缓存时间:

import os
default_time = os.getenv("GREAT_LIBRARY_CACHE_TIME", None)

在您的代码中使用@cache(default_time)。我不确定cache() API会将None作为默认参数,否则很容易修改收据以使其适应您的问题。

现在,great_library的用户可以在开发阶段(导入模块之前)通过os.putenv()或通过生产中的OS环境进行设置。

另一种放置挂钩的方法是使用配置模块导入。恕我直言,只有当你要设置一堆属性时,该方法才有用。如果您遵循该路径,则great_library模块应实现以下内容:

try:
    from great_library_config import *
except ImportError:
    # Default configurations like...
    default_time = None

我个人试图避免模块的解决方案,但对于具有高度可配置性的应用程序或框架非常有用。无论如何,在这种情况下,用户可以使用配置模块进行生产,并通过开发/测试来覆盖它。