Python pandas безопасный поток данных данных?

Я использую несколько потоков для доступа и удаления данных в моем фреймворке pandas. Из-за этого, мне интересно, pandas dataframe threadsafe?

Ответ 1

Данные в базовых ndarrays можно получить в потоковом режиме и изменить на свой страх и риск. Удаление данных было бы затруднительным, так как изменение размера DataFrame обычно требует создания нового объекта. Я бы хотел изменить это в какой-то момент в будущем.

Ответ 2

Нет, панды не безопасны. И это не безопасно потоком удивительными способами.

  • Можно ли читать с объекта панды, пока кто-то другой пишет на него?
  • Могу ли я скопировать фрейм данных pandas в свою ветку и поработать над копией?

Точно нет. Там давно открытый вопрос: https://github.com/pandas-dev/pandas/issues/2728

На самом деле, я думаю, что это довольно разумное (то есть ожидаемое) поведение. Я бы не ожидал, что смогу одновременно записывать и читать или копировать любую структуру данных, если только: (i) она не была разработана для параллелизма или ii) у меня нет исключительной блокировки этого объекта и всех объектов представления, полученных из это (.loc, .iloc - это представления, а у панд есть другие).

  • Можно ли читать с объекта панды, пока никто не пишет на него?

Почти для всех структур данных в Python ответ - да. Для панд нет. И, похоже, в настоящее время это не цель дизайна.

Как правило, вы можете выполнять операции "чтения" над объектами, если никто не выполняет мутации. Вы должны быть немного осторожны, хотя. Некоторые структуры данных, включая панд, выполняют запоминание для кэширования дорогостоящих операций, которые в остальном функционально чисты. Как правило, легко реализовать памятку без блокировки в Python:

@property
def thing(self):
    if _thing is MISSING:
        self._thing = self._calc_thing()
    return self._thing

... это просто и безопасно (при условии, что назначение безопасно атомарное - что не всегда было так для всех языков, но в CPython, если вы не переопределяете setattribute).

Панды, ряды и индексы данных рассчитываются лениво при первом использовании. Я надеюсь (но я не вижу гарантий в документах), что они сделаны аналогичным безопасным способом.

Для всех библиотек (включая панды) я хотел бы надеяться, что все типы операций только для чтения (или, более конкретно, "функционально чистые" операции) будут поточно-ориентированными, если никто не выполняет операции мутации. Я думаю, что это "разумный", легко достижимый, общий, более низкий уровень безопасности потоков.

Однако для панд вы не можете это предположить. Даже если вы можете гарантировать, что никто не выполняет "функционально нечистые" операции над вашим объектом (например, запись в ячейки, добавление/удаление столбцов), 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 !

... терпит неудачу для f(s): s.reindex(..., copy=True), который возвращает его в результате как новый объект - вы могли бы подумать, что он будет функционально чистым и поточно-ориентированным. К сожалению, это не так.

Результатом этого является то, что мы не могли использовать панд в производстве для нашей аналитической системы здравоохранения - и теперь я не одобряю ее для внутренней разработки, поскольку она делает распараллеливание в памяти операций только для чтения небезопасным. (!!)

Поведение reindex странное и удивительное. Если у кого-то есть идеи о том, почему он не работает, ответьте здесь: Каков источник небезопасности потоков при таком использовании pandas.Series.reindex(, copy = True)?

Сопровождающие пометили это как дубликат https://github.com/pandas-dev/pandas/issues/2728. Я подозрительно, но если источником является .copy, то почти все панды не защищены от потоков в любой ситуации (что является их советом).

Итак, чтобы ответить на оригинальный вопрос:

  • Могу ли я удалить из pandas dataframe, когда другой поток использует?

Fuggedaboutit!