python线程本地意外值

Posted

技术标签:

【中文标题】python线程本地意外值【英文标题】:python threading local unexpected value 【发布时间】:2021-12-24 12:54:42 【问题描述】:

为什么 getattr 不起作用?我没有尝试将默认值设置为 threadLocal,我想知道为什么 getattr 不能按我想要的方式工作?试图锁定,同样的输出

预期输出

0
1
2
3
4
main thread

电流输出

0
0
0
0
0
main thread

代码

from concurrent.futures import ThreadPoolExecutor
from threading import local

threadLocal = local()
threadLocal.x = 'main thread'

def f(x):
    # threadLocal.x = x # this works
    threadLocal.x = getattr(threadLocal, 'x', x) # this does not work
    return threadLocal.x

pool = ThreadPoolExecutor(5)
result = pool.map(f, range(0, 5))
for i in result:
    print(i)

print(threadLocal.x)

【问题讨论】:

线程本地附加到线程。其他线程中的更改不会影响主线程中的版本。而且新线程甚至看不到主线程中的x @KlausD 也许我没有解释清楚,但是threadLocal.x = x 做了我想要的,为什么使用 getattr 无法获得价值? 也许我也不够清楚:因为它在那个线程中不存在。 getattr(threadLocal, 'x', x) 中的x 不会是函数参数中的本地函数吗? @克劳斯D。 【参考方案1】:

线程 在工作项之间共享其工作线程。这意味着如果一个工作项在下一个工作项之前完成,那么两者都可以在同一个线程上运行,从而看到相同的线程局部变量。

这正是这里发生的情况:由于f 执行速度非常快,因此大多数或所有工作项都在第一个工作线程中运行。第一个任务f(0) 在此处设置threadLocal.x = 0,其他任务在同一线程中运行 因此读取threadLocal.x = 0

您可以通过(人为)增加f 的运行时间来规避此问题。

def f(x):
    time.sleep(0.2)  # delay for other work items to start running
    threadLocal.x = getattr(threadLocal, 'x', x) # this works now
    return threadLocal.x

请注意,任何额外操作可能足以解决计时问题:例如,这包括 printing 参数和线程本地。

【讨论】:

以上是关于python线程本地意外值的主要内容,如果未能解决你的问题,请参考以下文章

致命错误:在展开可选值错误 Swift 时意外发现 nil

Python - 数组复制/分配,numpy的意外'=array [:]'行为

想要将 Slidervalue 设置为 UserDefault:线程 1:致命错误:在隐式展开可选值时意外发现 nil [重复]

SVN-server发送了意外的返回值(405 Method Not Allowed)

TBB 线程池意外增加

什么会导致 .NET 进程/线程意外终止?