Pandas dataframe для Dockerized Postgres с использованием SQLAlchemy - PullRequest
0 голосов
/ 20 сентября 2018

Сводка в одну строку: Я бы хотел 1) Раскрутить базу данных Postgres, которая запускается в Docker 2) Заполнить эту базу данных PostgreSQL фреймом данных Pandas, используя SQLAlchemy извне контейнера .


Docker работает нормально:

CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                    NAMES
27add831cce5        postgres:10.1-alpine     "docker-entrypoint.s…"   2 weeks ago         Up 2 weeks          5432/tcp                 django-postgres_db_1

Мне удалось найти сообщения о получении фрейма данных pandas в Postgres и использовании SQLAlchemy для создания таблицы в Dockerized Postgres.,Соединяя это вместе, я получаю следующее, что (вроде) работает:

import numpy as np
import pandas as pd

from sqlalchemy import create_engine
from sklearn.datasets import load_iris


def get_iris():

    iris = load_iris()

    return pd.DataFrame(data=np.c_[iris['data'], iris['target']],
                        columns=iris['feature_names'] + ['target'])

df = get_iris()

print(df.head(n=5))

engine = create_engine(
    'postgresql://postgres:mysecretpassword@localhost:5432/postgres'.format(
    'django-postgres_db_1'))

df.to_sql('iris', engine)

Вопросы :

q.1 )Вышеупомянутое близко к предпочтительному способу сделать это?

q.2 ) Есть ли способ создать дБ в Postgres, используя SQLAlchemy?Например, мне не нужно вручную добавлять новый БД или заполнять стандартный Postgres.


Проблемы :

стр.1 ) Когда я запускаю create_engine, который «работает», я получаю следующую ошибку:

  File "/home/tmo/projects/toy-pipeline/venv/lib/python3.5/site-packages/sqlalchemy/dialects/postgresql/psycopg2.py", line 683, in do_executemany
    cursor.executemany(statement, parameters)
KeyError: 'sepal length (cm'

Однако, если я снова запускаю код, он говорит, что таблица радужной оболочки уже существует.Если я обращаюсь к базе данных Postgres вручную и выполняю postgres=# TABLE iris, она ничего не возвращает.

стр.2 ) У меня есть таблица в моей базе данных Postgres, работающей в Docker, которая называется testdb

postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 testdb    | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
(4 rows)

, но если я попытаюсь вставить эту таблицу вcreate_engine Я получаю сообщение об ошибке:

conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL:  database "testdb" does not exist

(обратите внимание, как postgres был заменен на testdb):

engine = create_engine(
    'postgresql://postgres:mysecretpassword@localhost:5432/testdb'.format(
    'django-postgres_db_1'))

Обновление :

Итак, я думаю, я выяснил, в чем может быть проблема: неправильное использование имени хоста и адреса.Я должен упомянуть, что я работаю на экземпляре Azure в Ubuntu 16.04.

Вот некоторая полезная информация о контейнере, на котором выполняется Postgres:

HOSTNAME=96402054abb3
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/postgresql/10/bin
PGDATA=/var/lib/postgresql/data
PG_MAJOR=10
PG_VERSION=10.5-1.pgdg90+1

И о etc/hosts

127.0.0.1   localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2  96402054abb3

Как мне сконструировать мойСтрока подключения правильно? Я пробовал:

Имя контейнера, как предлагается здесь :

engine = create_engine(
    'postgresql://postgres:saibot@{}:5432/testdb'.format(
    'c101519547f8e89c3422ca9e1dc68d85ad9f24bd8e049efb37273782540646f0'))

OperationalError: (psycopg2.OperationalError) could not translate host name "96402054abb3" to address: Name or service not known

, и я попытался вставить ip, localhost, HOSTNAME и т. Д. Без удачи.

Я использую этот фрагмент кода, чтобы проверить, подключается ли БД:

from sqlalchemy import create_engine
from sqlalchemy_utils import database_exists

engine = create_engine(
    'postgresql://postgres:saibot@172.17.0.2/testdb')

database_exists(engine.url)

1 Ответ

0 голосов
/ 21 сентября 2018

Я решил это, вставив ip хоста контейнера: 172.17.0.2 в строку подключения следующим образом:

'postgresql://postgres:mysecretpasswd@172.17.0.2/raw_data'

Что в сочетании с функцией решило мою проблему:

def db_create(engine_url, dataframe):
    """
    Check if postgres db exists, if not creates it
    """

    engine = create_engine(engine_url)

    if not database_exists(engine.url):
        print("Database does not exist, creating...")
        create_database(engine.url)

    print("Does it exist now?", database_exists(engine.url))

    if database_exists(engine.url):
        data_type = str(engine.url).rsplit('/', 1)[1]
        print('Populating database with', data_type)
        dataframe.to_sql(data_type, engine)

db_create('postgresql://postgres:mysecretpasswd@172.17.0.2/raw_data')

создаст базу данных с именем raw_data с таблицей с именем raw_data и заполнит ее целевым фреймом данных Pandas.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...