我正在使用多个线程来访问和删除我的pandas数据框中的数据。因此,我想知道pandas dataframe是线程安全的吗?
uttx8gqw1#
不,pandas不是线程安全的。而且它的线程安全性并不令人惊讶。
该死的!没有。一般来说也没有。即使是GIL锁定的Python数据结构也不行。
绝对不是有一个长期悬而未决的问题https://github.com/pandas-dev/pandas/issues/2728我认为这是相当合理的(即。预期)行为。我不希望能够同时读写任何数据结构,除非:i)它是为并发而设计的,或者ii)我对该对象 * 和从它派生的所有视图对象 * 有一个排他锁(.loc,.iloc是视图,pandas有其他视图)。
.loc
.iloc
对于Python中几乎所有的数据结构,答案都是肯定的。对于Pandas来说,不是。这似乎不是目前的设计目标。通常,如果没有人在执行变异操作,则可以对对象执行“读取”操作。不过,你得谨慎一点。一些数据结构,包括pandas,执行memoization,以缓存昂贵的操作,否则功能纯。在Python中实现无锁记忆通常很容易:
@property def thing(self): if _thing is MISSING: self._thing = self._calc_thing() return self._thing
...它简单而安全(假设赋值是安全原子的--这并不总是每个语言的情况,但在CPython中是这样的,除非你重写__setattribute__)。pandas、series和dataframe索引在第一次使用时是延迟计算的。我希望(但我没有看到文档中的保证),它们以类似的安全方式完成。对于所有的库(包括pandas),我希望所有类型的只读操作(或者更具体地说,“纯功能”操作)都是线程安全的,如果没有人执行变异操作。我认为这是一个“合理”容易实现的,常见的,较低的线程安全条。然而,对于Pandas,你不能这样假设。* 即使你可以保证没有人在你的对象上执行“功能上不纯”的操作(例如写入单元格,添加/删除列'),pandas不是线程安全的。*这里有一个最近的例子:https://github.com/pandas-dev/pandas/issues/25870(它被标记为. copy-not-threadsafe问题的重复,但似乎它可能是一个单独的问题)。
__setattribute__
s = pd.Series(...) f(s) # Success! # Thread 1: while True: f(s) # Thread 2: while True: f(s) # Exception !
...对于f(s): s.reindex(..., copy=True)失败,它返回的结果a作为新对象--你会认为它在功能上是纯的,线程安全的。不幸的是,事实并非如此。这样做的结果是,我们无法在生产环境中为我们的医疗分析系统使用pandas,我现在不鼓励它用于内部开发,因为它使得只读操作的内存并行化不安全。(!!)reindex的行为是怪异和令人惊讶的。如果有人对它失败的原因有想法,请在这里回答:What's the source of thread-unsafety in this usage of pandas.Series.reindex(, copy=True)?维护者将其标记为https://github.com/pandas-dev/pandas/issues/2728的副本。我很怀疑,但是如果.copy是源代码,那么 * 几乎所有的pandas * 在任何情况下都不是线程安全的(这是他们的建议)。!
f(s): s.reindex(..., copy=True)
reindex
.copy
pbgvytdp2#
底层ndarray中的数据可以以线程安全的方式访问,并由您自行承担修改风险。删除数据会很困难,因为更改DataFrame的大小通常需要创建一个新对象。我想在未来的某个时候改变这个。
2条答案
按热度按时间uttx8gqw1#
不,pandas不是线程安全的。而且它的线程安全性并不令人惊讶。
该死的!没有。一般来说也没有。即使是GIL锁定的Python数据结构也不行。
绝对不是有一个长期悬而未决的问题https://github.com/pandas-dev/pandas/issues/2728
我认为这是相当合理的(即。预期)行为。我不希望能够同时读写任何数据结构,除非:i)它是为并发而设计的,或者ii)我对该对象 * 和从它派生的所有视图对象 * 有一个排他锁(
.loc
,.iloc
是视图,pandas有其他视图)。对于Python中几乎所有的数据结构,答案都是肯定的。对于Pandas来说,不是。这似乎不是目前的设计目标。
通常,如果没有人在执行变异操作,则可以对对象执行“读取”操作。不过,你得谨慎一点。一些数据结构,包括pandas,执行memoization,以缓存昂贵的操作,否则功能纯。在Python中实现无锁记忆通常很容易:
...它简单而安全(假设赋值是安全原子的--这并不总是每个语言的情况,但在CPython中是这样的,除非你重写
__setattribute__
)。pandas、series和dataframe索引在第一次使用时是延迟计算的。我希望(但我没有看到文档中的保证),它们以类似的安全方式完成。
对于所有的库(包括pandas),我希望所有类型的只读操作(或者更具体地说,“纯功能”操作)都是线程安全的,如果没有人执行变异操作。我认为这是一个“合理”容易实现的,常见的,较低的线程安全条。
然而,对于Pandas,你不能这样假设。* 即使你可以保证没有人在你的对象上执行“功能上不纯”的操作(例如写入单元格,添加/删除列'),pandas不是线程安全的。*
这里有一个最近的例子:https://github.com/pandas-dev/pandas/issues/25870(它被标记为. copy-not-threadsafe问题的重复,但似乎它可能是一个单独的问题)。
...对于
f(s): s.reindex(..., copy=True)
失败,它返回的结果a作为新对象--你会认为它在功能上是纯的,线程安全的。不幸的是,事实并非如此。这样做的结果是,我们无法在生产环境中为我们的医疗分析系统使用pandas,我现在不鼓励它用于内部开发,因为它使得只读操作的内存并行化不安全。(!!)
reindex
的行为是怪异和令人惊讶的。如果有人对它失败的原因有想法,请在这里回答:What's the source of thread-unsafety in this usage of pandas.Series.reindex(, copy=True)?维护者将其标记为https://github.com/pandas-dev/pandas/issues/2728的副本。我很怀疑,但是如果
.copy
是源代码,那么 * 几乎所有的pandas * 在任何情况下都不是线程安全的(这是他们的建议)。!
pbgvytdp2#
底层ndarray中的数据可以以线程安全的方式访问,并由您自行承担修改风险。删除数据会很困难,因为更改DataFrame的大小通常需要创建一个新对象。我想在未来的某个时候改变这个。