为什么 Pandas 和 GeoPandas 能够使用 DBAPI (psycopg2) 连接读取数据库表,但必须依赖 SQLAlchemy 来编写数据库表?

s.k*_*s.k 6 sqlalchemy psycopg2 dataframe pandas geopandas

语境

我在尝试从脚本对某些数据库执行一些 I/O 操作时遇到了麻烦Python3

当我想要连接到数据库时,我习惯性地使用psycopg2to 来处理连接游标

我的数据通常存储为and/or的等效项。 Pandas DataFramesGeoPandasGeoDataFrames

困难

为了数据库表中读取数据;

使用Pandas

我可以依赖它.read_sql()作为参数的方法con,如文档中所述:

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>`_
Run Code Online (Sandbox Code Playgroud)

使用GeoPandas

我可以依赖它.read_postigs()作为参数的方法con,如文档中所述:

con : DB connection object or SQLAlchemy engine
        Active connection to the database to query.
Run Code Online (Sandbox Code Playgroud)

为了将数据写入数据库表

使用Pandas

我可以依赖.to_sql()作为参数的方法con,如文档中所述:

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>`_
Run Code Online (Sandbox Code Playgroud)

使用GeoPandas

我可以依赖作为参数的.to_sql()方法(直接依赖于) ,如文档中所述:Pandas .to_sql()con

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>`_
Run Code Online (Sandbox Code Playgroud)

从这里,我很容易理解它是专门为其对象GeoPandas构建的,很快,它就是一个可以处理地理数据的特殊对象。PandasGeoDataFrameDataFrame

但我想知道为什么 doGeoPandas能够直接将psycopg2连接作为参数而不是,Pandas以及是否计划用于后者?

为什么在写入数据时,两者的情况都不一样?
我想(可能和其他许多人一样1,2)直接给他们一个连接参数,而不是依赖于engine。 因为即使这个工具真的很棒,它也让我使用两个不同的框架来连接到我的数据库,从而处理两个不同的连接字符串(我个人更喜欢处理字典中的参数扩展以正确构建连接字符串的方式,例如;与URL注入的解释如下,例如:Is it possible to pass adictionary into create_engine function in SQLAlchemy?)。psycopg2 SQLAlchemy
psycopg2psycopg2.connect(**dict_params)

解决方法

  1. psycopg2我首先使用参数字典 创建连接字符串,如下所示:

    connParams = ("user={}", "password={}", "host={}", "port={}", "dbname={}")
    conn = ' '.join(connParams).format(*dict_params.values())
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后我发现这样更好,更Pythonic:

    conn = psycopg2.connect(**dict_params)
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我最终用它替换了它,这样我就可以互换地使用它来构建连接或引擎: psycopg2 SQLAlchemy

    def connector():
        return psycopg2.connect(**dict_params)
    
    Run Code Online (Sandbox Code Playgroud)

    a)初始化连接现在通过以下方式完成:psycopg2

    conn = connector()
    curs = conn.cursor()
    
    Run Code Online (Sandbox Code Playgroud)

    b)并通过以下方式初始化引擎SQLAlchemy

    engine = create_engine('postgresql+psycopg2://', creator=connector)
    
    Run Code Online (Sandbox Code Playgroud)

(或与您的任何口味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 Alchemy 引擎将数据帧转换为 sql
[2]如何在不使用 SQLAlchemy 引擎的情况下将数据帧写入 Postgres 表?

Gor*_*son 7

to_sql可能需要 SQLAlchemy ConnectableEngine或)对象的主要原因Connectionto_sql需要能够创建数据库表(如果它不存在或需要替换)。pandas 的早期版本专门使用 DBAPI 连接,但我怀疑当他们添加新功能时,to_sql他们发现自己编写了大量特定于数据库的代码来解决各种 DDL 实现的怪癖。

在意识到他们复制了 SQLAlchemy 中已有的大量逻辑后,他们可能决定将所有复杂性“外包”给 SQLAlchemy 本身,只需接受Engine/Connection对象并使用 SQLAlchemy 的(独立于数据库的)SQL 表达式语言来创建表。

它使我使用两个不同的框架来连接到我的数据库

不,因为.read_sql_query()还接受 SQLAlchemyConnectable对象,因此您可以仅使用 SQLAlchemy 连接进行读取和写入。

  • 这是正确的。将数据写入数据库需要大量特定于数据库风格的代码,这些代码由 SQLAlchemy 处理。读取数据(至少在基于 SELECT 查询时)仅接收结果集,并且可以更普遍地完成。 (4认同)
  • 像psycopg2这样的DBAPI接口层是根据[DBAPI规范](https://www.python.org/dev/peps/pep-0249/)编写的,它主要涉及向数据库服务器发送任意SQL语句并接收结果。他们完全有能力向数据库发送“CREATE TABLE”语句,但他们不知道如何构造这样的语句,因为这“不是他们的工作”;这是其他人要担心的,而对于 pandas 来说,“其他人”就是 SQLAlchemy。 (2认同)