通过将属性合并/更新到模块的命名空间来加载一次配置

问题描述 投票:2回答:1

在Python中使用以下配置单例类:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function
from builtins import *
import sys

class Config(object):

    __instance = None

    def __new__(cls):
        if cls.__instance is None:
            cls.__instance = super(Config, cls).__new__(cls)
            cls.__instance.__initialized = False
        return cls.__instance

    def __init__(self):
        print('INIT')
        if self.__initialized: 
            return
        self.__initialized = True

        self._defaults = {"foo": True, "bar": False}

        for k, v in self._defaults.items():
            setattr(self, k, v)

    def reload(self):
        print(self)
        if not self._defaults:
            return
        for k, v in self._defaults.items():
            setattr(self, k, v)

我可以编写一个测试来验证属性设置并正确更新:

import config; config = config.Config()

print(config)
print(config.foo)
assert(config.foo is True)
config.foo = False
print(config.foo)
assert(config.foo is False)

config.reload()
print(config.foo)
assert(config.foo is True)

输出:

INIT
<config.Config object at 0x10bbf73d0>
True
False
<config.Config object at 0x10bbf73d0>
True

这工作正常,但我的OCD无法处理我必须导入配置并执行其主类。

我尝试将sys.modules[__name__] = Config()添加到config.py的底部,这样我就可以做import config,但它在reload()上有:

TypeError: 'NoneType' object is not callable

奇怪的是,我只是期望它抱怨模块命名空间上没有更新这些值,但它似乎是事先破坏 - 只是试图执行reload()

我在这里运气不好吗?或者是否有一些神奇的方式我可以用reload()和单线import config工作?

python python-3.x namespaces python-module
1个回答
2
投票

当你reload它不起作用的原因是因为在分配给sys.modules[__name__]后,模块及其内置函数被垃圾收集并用None替换。我假设你知道这个,因为你from builtins import *。但是,导入的内置也将被垃圾收集。

要解决此问题,您可以在reload中导入内置函数,以便使用不会收集垃圾的版本。

旁注:这是未经测试的,因为我无法重现你的问题here,但我相信它会发生,因为该网站在进口方面可能会不稳定。

© www.soinside.com 2019 - 2024. All rights reserved.