在使用pandas.Series.reindex(,copy = True)时,线程不安全的根源是什么?

时间:2019-03-25 22:10:01

标签: python multithreading pandas

调用pd.Series.reindex并不是线程安全的(https://github.com/pandas-dev/pandas/issues/25870)。 我的问题是,即使没有人向该对象的数据写入数据,为什么Series.reindex(它返回一个副本并看起来像是功能上纯净的操作)为什么不是线程安全的?

我正在执行的操作是:

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

那么,为什么线程调用失败?我对此感到惊讶,因为如果有任何非线程安全的调用,例如填充Series的索引,我会以为它们会在主线程中完成它们的变异工作。

熊猫确实有一个未解决的问题,即.copy不是线程安全的。但是,这里的讨论围绕人们同时读写对象的问题。 https://github.com/pandas-dev/pandas/issues/2728

维护者将.reindex的非线程安全问题标记为https://github.com/pandas-dev/pandas/issues/2728的重复项。我怀疑其原因是相同的,但是如果以.copy为来源,那么我怀疑在任何情况下,几乎所有熊猫都不是线程安全的,因为它们都是“功能纯净的”操作。

import traceback
import pandas as pd
import numpy as np
from multiprocessing.pool import ThreadPool

def f(arg):
    s,idx = arg
    try:
        # s.loc[idx].values   # No problem
        s.reindex(idx) # Fails
    except Exception:
        traceback.print_exc()
    return None


def gen_args(n=10000):
    a = np.arange(0, 3000000)
    for i in xrange(n):
        if i%1000 == 0:
            # print "?",i
            s = pd.Series(data=a, index=a)
            f((s,a)) # <<< LOOK. IT WORKS HERE!!!
        yield s, np.arange(0,1000)

# for arg in gen_args():
#     f(arg)   # Works fine

t = ThreadPool(4)
for result in t.imap(f, gen_args(), chunksize=1):
    # print "==>", result
    pass

0 个答案:

没有答案