首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何制作2.7python上下文管理器线程安全

如何制作2.7python上下文管理器线程安全
EN

Stack Overflow用户
提问于 2015-10-29 06:41:51
回答 1查看 1.2K关注 0票数 10

我有一个大型python应用程序,它运行在Django服务上。我需要关闭某些操作的权限测试,所以我创建了这个上下文管理器:

代码语言:javascript
复制
class OverrideTests(object):

    def __init__(self):
        self.override = 0

    def __enter__(self):
        self.override += 1

    # noinspection PyUnusedLocal
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.override -= 1
        assert not self.override < 0

    @property
    def overriding(self):
        return self.override > 0

override_tests = OverrideTests()

然后,应用程序的各个部分可以使用上下文管理器覆盖测试:

代码语言:javascript
复制
with override_tests:
    do stuff
    ...

在do中,上面的上下文管理器可以在不同的函数中多次使用。计数器的使用控制住了这一切,而且它似乎运转良好.直到线索介入。

一旦涉及到线程,全局上下文管理器就会被重用,因此,测试可能会被错误地覆盖。

下面是一个简单的测试用例--如果thread.start_new_thread(do_id, ())行被一个简单的do_it替换,但是异常失败,这很好,如图所示:

代码语言:javascript
复制
def stat(k, expected):
    x = '.' if override_tests.overriding == expected else '*'
    sys.stdout.write('{0}{1}'.format(k, x))


def do_it_inner():
    with override_tests:
        stat(2, True)
    stat(3, True)  # outer with context makes this true


def do_it():
    with override_tests:
        stat(1, True)
        do_it_inner()
    stat(4, False)


def do_it_lots(ntimes=10):
    for i in range(ntimes):
        thread.start_new_thread(do_it, ())

我如何使这个上下文管理器线程安全,以便在每个Python线程中,即使它是可重用的,它也可以被一致使用?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-02 05:03:19

下面是一种可行的方法:使您的OverrideTests类成为threading.local的子类。为了安全起见,您应该在您的__init__中调用超类__init__ (尽管它似乎工作,即使您没有):

代码语言:javascript
复制
class OverrideTests(threading.local):

    def __init__(self):
        super(OverrideTests, self).__init__()
        self.override = 0

    # rest of class same as before

override_tests = OverrideTests()

然后:

代码语言:javascript
复制
>>> do_it_lots()
1.1.1.2.2.1.1.1.1.1.1.3.3.2.2.2.2.2.2.4.4.3.1.3.3.3.3.4.3.2.4.4.2.4.3.4.4.4.3.4.

但是,我不会把钱花在这种情况下,尤其是如果您的实际应用程序比您在这里展示的示例更复杂的话。最终,你真的应该重新考虑你的设计。在您的问题中,您关注的是如何“使上下文管理器线程安全”。但真正的问题不仅在于上下文管理器,还在于您的函数(在您的示例中是stat)。stat依赖全局状态(全局override_tests),它在线程环境中本质上是脆弱的。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33407515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档