Почему Pandas и Geo Pandas могут читать таблицу базы данных, используя соединение psycopg2, но для ее записи приходится полагаться на SQLAlchemy? - PullRequest
1 голос
/ 10 февраля 2020

Контекст

У меня просто возникают проблемы при попытке выполнить некоторые операции ввода-вывода в некоторых базах данных из сценария Python3.

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

Мои данные обычно хранятся как Pandas DataFrames и / или GeoPandas в эквиваленте GeoDataFrames.

Трудности

Чтобы прочитать данные из таблицы базы данных;

Используя Pandas:

Я могу положиться на его .read_sql() методы, которые принимают в качестве параметра con, как указано в do c:

con : SQLAlchemy connectable (engine/connection) or database str URI
        or DBAPI2 connection (fallback mode)'
        Using SQLAlchemy makes it possible to use any DB supported by that
        library. If a DBAPI2 object, only sqlite3 is supported. The user is responsible
        for engine disposal and connection closure for the SQLAlchemy connectable. See
        `here <https://docs.sqlalchemy.org/en/13/core/connections.html>`_

Используя GeoPandas:

, я могу положиться на его методы .read_postigs(), который принимает в качестве параметра con, как указано в do c:

con : DB connection object or SQLAlchemy engine
        Active connection to the database to query.

Чтобы записать данные в таблицу базы данных;

Используя Pandas:

Я могу положиться на методы .to_sql(), которые принимают в качестве параметра con, как указано в do c:

con : sqlalchemy.engine.Engine or sqlite3.Connection
        Using SQLAlchemy makes it possible to use any DB supported by that
        library. Legacy support is provided for sqlite3.Connection objects. The user
        is responsible for engine disposal and connection closure for the SQLAlchemy
        connectable See `here                 <https://docs.sqlalchemy.org/en/13/core/connections.html>`_

Использование GeoPandas:

Я могу положиться на методы .to_sql() (которые напрямую зависят от Pandas .to_sql()), который принимает в качестве параметра con, как указано в do c:

con : sqlalchemy.engine.Engine or sqlite3.Connection
        Using SQLAlchemy makes it possible to use any DB supported by that
        library. Legacy support is provided for sqlite3.Connection objects. The user
        is responsible for engine disposal and connection closure for the SQLAlchemy
        connectable See `here                 <https://docs.sqlalchemy.org/en/13/core/connections.html>`_

Отсюда, я легко понимаю, что GeoPandas построен на Pandas особенно f или его GeoDataFrame объект, который в скором времени является специальным DataFrame, который может обрабатывать географические данные c.

Но мне интересно, почему do GeoPandas имеет возможность напрямую принимать соединение psycopg2 в качестве аргумента, а не Pandas, и планируется ли оно для последнего?

И почему ни то, ни другое не имеет отношения к записи данных?
Я бы хотел (как, наверное, многие другие 1,2 ), чтобы напрямую дать им psycopg2 аргумент вместо того, чтобы полагаться на SQLAlchemy engine .
Потому что даже если этот инструмент действительно хорош, он заставляет меня использовать две разные платформы для подключения к моей базе данных и, таким образом, обрабатывать две разные строки подключения (и я лично предпочитаю, чтобы psycopg2 обрабатывал расширение параметров из словаря чтобы правильно построить строку подключения, такую ​​как; psycopg2.connect(**dict_params) против URL внедрение, как описано здесь, например: Можно ли передать словарь в функцию create_engine в SQLAlchemy? ).

Обходной путь

  1. Сначала я создавал строку подключения с помощью psycopg2 из словаря параметров следующим образом:

    connParams = ("user={}", "password={}", "host={}", "port={}", "dbname={}")
    conn = ' '.join(connParams).format(*dict_params.values())
    
  2. Тогда я понял, что это будет и так далее pythoni c таким образом:

    conn = psycopg2.connect(**dict_params)
    
  3. Который я наконец заменил этим, чтобы я мог взаимозаменяемо использовать его для построения либо psycopg2 соединения или SQLAlchemy двигатель:

    def connector():
        return psycopg2.connect(**dict_params)
    

    a) Инициализация psycopg2 соединения теперь выполняется:

    conn = connector()
    curs = conn.cursor()
    

    b) И инициализировать SQLAlchemy двигатель с помощью:

    engine = create_engine('postgresql+psycopg2://', creator=connector)
    

(или с любым из ваших ароматизированных db+driver)

Это хорошо задокументировано здесь:
https://docs.sqlalchemy.org/en/13/core/engines.html#custom -dbapi-args
и здесь:
https://docs.sqlalchemy.org/en/13/core/engines.html#sqlalchemy .create_engine


[1] Кадр данных sql без Sql Алхимический двигатель
[2] Как записать фрейм данных в таблицу Postgres без использования движка SQLAlchemy?

1 Ответ

1 голос
/ 10 февраля 2020

Вероятно, основная причина, по которой to_sql нужен объект Engine, заключается в том, что to_sql должна иметь возможность создавать таблицу базы данных, если она не существует или ее необходимо заменить. Ранние версии pandas работали исключительно с соединениями DBAPI, но я подозреваю, что, когда они добавляли новые функции в to_sql, они обнаружили, что пишут много специфичного для базы данных кода c, чтобы обойти причуды различных реализаций DDL. ,

Поняв, что они дублируют большое количество логик c, которые уже были в SQLAlchemy, они, вероятно, решили "перенести" всю эту сложность на саму SQLAlchemy, просто приняв объект Engine и используя SQLAlchemy ( не зависит от базы данных) SQL Язык выражений для создания таблицы.

...