python pandas dataframe线程安全吗?

And*_*rew 10 python thread-safety pandas

我使用多个线程来访问和删除我的pandas数据帧中的数据.因此,我想知道是pandas dataframe threadsafe吗?

use*_*956 25

不,pandas 不是线程安全的。而且它以令人惊讶的方式不是线程安全的。

  • 当另一个线程正在使用时,我可以从 Pandas 数据帧中删除吗?

胡说八道!不。一般不会。甚至不适用于 GIL 锁定的 python 数据结构。

  • 我可以在其他人写入时读取 pandas 对象吗?
  • 我可以在我的线程中复制一个 Pandas 数据框,然后处理副本吗?

当然不。有一个长期存在的未决问题:https : //github.com/pandas-dev/pandas/issues/2728

实际上我认为这是非常合理的(即预期的)行为。我不希望能够同时写入和读取或复制任何数据结构,除非:i)它是为并发而设计的,或者 ii)我对该对象和所有派生自的视图对象有一个排他锁.loc,.iloc是观点,而大熊猫可能有其他观点)。

  • 我可以在没有其他人写入的情况下读取 pandas 对象吗?

对于 Python 中的几乎所有数据结构,答案都是肯定的。对于熊猫,没有。看起来,它目前不是一个设计目标。

通常,如果没有人执行变异操作,您可以对对象执行“读取”操作。不过,您必须谨慎一些。一些数据结构,包括 Pandas,执行记忆化,以缓存昂贵的操作,否则这些操作在功能上是纯的。在 Python 中实现无锁记忆通常很容易:

@property
def thing(self):
    if _thing is MISSING:
        self._thing = self._calc_thing()
    return self._thing
Run Code Online (Sandbox Code Playgroud)

...它简单而安全(假设赋值是安全的原子性——并非每种语言总是如此,但在 CPython 中,除非你覆盖setattribute)。

Pandas、series 和 dataframe 索引在第一次使用时是惰性计算的。我希望(但我没有在文档中看到保证),它们是以类似的安全方式完成的。

对于所有库(包括熊猫),如果没有人执行变异操作,我希望所有类型的只读操作(或更具体地说,“功能纯”操作)都是线程安全的。我认为这是一个“合理的”容易实现的、常见的、线程安全性较低的标准。

但是,对于熊猫,您不能假设这一点。即使您可以保证没有人对您的对象执行“功能上不纯”的操作(例如写入单元格、添加/删除列),pandas 也不是线程安全的。

这是最近的一个例子:https : //github.com/pandas-dev/pandas/issues/25870(它被标记为 .copy-not-threadsafe 问题的重复,但它似乎可能是一个单独的问题)。

s = pd.Series(...)
f(s)  # Success!

# Thread 1:
   while True: f(s)  

# Thread 2:
   while True: f(s)  # Exception !
Run Code Online (Sandbox Code Playgroud)

... 失败 for f(s): s.reindex(..., copy=True),它将结果作为新对象返回 - 您会认为它在功能上是纯的并且是线程安全的。不幸的是,事实并非如此。

这样做的结果是我们无法在生产中为我们的医疗保健分析系统使用 Pandas - 我现在不鼓励在内部开发中使用它,因为它使只读操作的内存并行化变得不安全。(!!)

这种reindex行为很奇怪,也很令人惊讶。如果有人对其失败的原因有任何想法,请在此处回答: pandas.Series.reindex(, copy=True) 的这种用法中线程不安全的根源是什么?

维护者将此标记为https://github.com/pandas-dev/pandas/issues/2728的副本 。我很怀疑,但如果.copy是来源,那么几乎所有的熊猫在任何情况下都不是线程安全的(这是他们的建议)。


Wes*_*ney 12

底层ndarrays中的数据可以以线程安全的方式访问,并且需要自行修改.删除数据很困难,因为更改DataFrame的大小通常需要创建一个新对象.我想在将来的某个时候改变它.

  • 那么,这是否意味着从多个线程追加到DataFrame是线程安全的? (3认同)