gpt4 book ai didi

python - 我如何使 2.7 python 上下文管理器线程安全

转载 作者:太空狗 更新时间:2023-10-29 18:34:04 25 4
gpt4 key购买 nike

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

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()

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

with override_tests:
do stuff
...

在 do stuff 中,上述上下文管理器可能会在不同的函数中多次使用。计数器的使用使它处于控制之下并且它似乎工作正常......直到线程介入。

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

这是一个简单的测试用例 - 如果 thread.start_new_thread(do_id, ()) 行被简单的 do_it 替换,这会工作正常,但会失败,如图所示:

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 线程中,即使它是可重入的,它也始终如一地被使用?

最佳答案

这是一种似乎有效的方法:使您的 OverrideTests 类成为 threading.local 的子类。为了安全起见,您应该在 __init__ 中调用父类(super class) __init__(尽管即使您不这样做,它似乎也能工作):

class OverrideTests(threading.local):

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

# rest of class same as before

override_tests = OverrideTests()

然后:

>>> 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),这在线程环境中本质上是脆弱的。

关于python - 我如何使 2.7 python 上下文管理器线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33407515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com