Python pandas висит в контейнере docker для небольшого объема данных

Я пытаюсь загрузить данные размером 44 МБ во фрейм данных Pandas. это код:

import pandas as pd
from sqlalchemy import create_engine
import cx_Oracle
import sqlalchemy

engineor = create_engine('oracle+cx_oracle://xxxxx:xxx@xxx:1521/?service_name=XXX')
sql = "select * from accounts where date >= '10-MAY-18 06.00.16.170000000 PM'"
do = pd.read_sql(sql, engineor)
do.info(memory_usage='deep')

Вышеупомянутый запрос возвращает около 70 тыс. Строк, а размер составляет около 44 МБ.

Когда я запускаю это со своего локального компьютера (Win 7) в Anaconda, данные загружаются во фрейм данных без каких-либо проблем через минуту или две. Однако, когда я запускаю то же самое в контейнере Docker (на базе Linux), оно просто зависает.

Я проверил, что в контейнере докеров достаточно памяти, и память не увеличивается со временем (хотя размер довольно небольшой ~ 44 Мб). Он просто отправляется и зависает на неопределенный срок, поэтому я не могу его убить, нажав Ctrl + C или Control + Z. Мне нужно отключиться от машины и снова войти в систему.

Я попытался сопоставить версию Pandas от Anaconda, которую я запускаю на локальной машине. Но это не сильно помогло, все еще висит. Единственное, что сейчас отличается между моей локальной машиной и версией Python. В контейнере докеров это 3.5.3, а в моей локальной версии - 3.6.3, и эта Anaconda запускается из Windows, а контейнер докеров основан на Linux. Я не уверен, имеют ли эти вещи какое-то значение.

Любые предложения о том, как это преодолеть?

Я подозреваю, что ваш контейнер не может получить доступ к базе данных Oracle. Вы можете попробовать получить журналы для контейнера (определите идентификатор контейнера с помощью docker [ps|container] ls, а затем docker logs [ID]. Если ваш образ контейнера включает оболочку, вы можете попытаться получить доступ к оболочке и проверить связь с БД: docker exec --interactive --tty [ID] bash (если не bash, попробуйте sh и ash). Я подозреваю, что из-за того, что вы используете хост Windows, вам нужно запустить Docker на виртуальной машине, и, следовательно, сеть хоста (и ваши DNS-имена) не распространяются на ваш контейнер.

DazWilkin 10.08.2018 17:05

Могу подтвердить, что таких вопросов нет. Он может загружать данные без каких-либо проблем, если объем невелик (от 100 до нескольких тысяч) постоянно. Это приводит к этой проблеме, когда объем оказывается большим. Еще одно непоследовательное поведение заключается в том, что ... когда я пытался загрузить 30 тыс. Строк, иногда это срабатывало, а в большинстве случаев зависало.

CuriP 10.08.2018 17:14

Вы запускаете Docker в виртуальной машине на машине с Windows? Возможно, ресурсы ограничены виртуальной машиной и / или возникают проблемы с сетью в этой конфигурации. Я не знаком с Docker в Windows. Вы что-нибудь видели в журналах?

DazWilkin 10.08.2018 17:21

Он находится на машине Linux, и это не виртуальная машина. Журнал Python просто застрял на первом шаге без каких-либо обновлений. Я также попытался запустить приведенный выше код в режиме командной строки, потому что журналы не помогли, но, как я упоминал ранее, он просто зависает, не имея возможности выйти с помощью Control C или Control Z. Это более или менее похоже на эту проблему ( кроме моего - read_sql) .. stackoverflow.com/questions/48430886/… .. Я не уверен, как включить обходной путь, который он предложил.

CuriP 10.08.2018 17:34

Не уверен. Вы май хотите попробовать разбить чтение (см. pandas.pydata.org/pandas-docs/stable/generated/…).

DazWilkin 10.08.2018 17:47

Спасибо .. Я тоже пробовал разбивать на части. Это не помогло. Я попытался установить даже 100 строк, это не сработало, когда общие строки, с которыми нужно работать, большие. Я считаю, что, несмотря на разбиение на фрагменты, Pandas действительно переносит полные данные в какую-то форму памяти ОС и начинает загружаться во фреймы данных в виде фрагментов, так что фактически он работает с полным объемом, только это скрывается синтаксически.

CuriP 10.08.2018 18:28

Я запускал куски в командной строке и заметил, что она зависает после чтения определенного количества строк. Он варьируется от таблицы к таблице ... он читает 9500 строк для таблицы A и 135k строк перед зависанием ... предположение зависит от объема, который приносит каждая таблица. Я не уверен, почему он застревает. В ОС достаточно памяти. Он останавливается при определенном использовании памяти .. (~ 500 МБ) каждый раз (доступно до 8 ГБ) .. очистка памяти с помощью del, gc.collect и пустой фрейм данных мало помогает. Есть ли способ заставить Python Pands запрашивать больше памяти у ОС? Или каким-либо способом очистить память в цикле for с помощью кусков?

CuriP 10.08.2018 19:25

Я недостаточно хорошо знаю Панд, чтобы помочь. Надеюсь, у кого-то здесь есть ответ. Удачи!

DazWilkin 10.08.2018 23:57
1
8
365
1

Ответы 1

Я столкнулся с той же проблемой, что и ваша. Думаю, это из-за использования сокетной связи внутри контейнера сети моста.

Docker по умолчанию использует мостовую сеть, только назначенные порты могут быть перенаправлены на хост. Обычно это работает, когда вы используете контейнер в качестве сервера. Но когда ваш контейнер работает как клиент, который создает сокеты для связи, возникнет проблема.

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

Мое решение - запускать контейнеры с использованием хост-сети. Вы можете запустить контейнер, используя команду вроде

docker run --rm -d --network host --name my_nginx nginx

или используя docker-compose

version: '3.7'
services:
  my_nginx:
    ...
    network_mode: "host"

Но будьте осторожны, использование хост-сети может вызвать конфликты портов.

PS. Хотя использование хост-сети решило мою проблему, я не специалист по сокетам или сетям. Пожалуйста, поправьте меня, если я ошибаюсь насчет механизима. Я прочитал сокет в этой статье: https://docs.oracle.com/javase/tutorial/networking/sockets/definition.html.

Другие вопросы по теме