SQLAlchemy engine.connect() 使用密钥对身份验证对 Snowflake 失败

SQLAlchemy engine.connect() fails for Snowflake using keypair authentication

我的目标是能够使用 to_sql() 函数将 pandas 数据帧写入 Snowflake。我可以使用 read_sql() 从 Snowflake 成功查询,没有任何问题。 to_sql() 似乎需要一个我无法弄清楚的略有不同的配置。我尝试了下面概述的两种不同方法。

我猜,但密钥对身份验证似乎是问题所在,这可能是错误的。当我在这两种方法中删除私钥参数时,我都会收到密码丢失的错误,而不是我收到的特别不清楚的错误。也许没有指定密码会使尝试短路,我真的有另一个问题。

或者,如果有更好的方法将整个 pandas 数据帧写入 Snowflake,我很乐意接受其他选择。

方法一雪花连接器

编辑:如果连接不是 SQLAlchemy 连接,那么 sqllite 似乎是唯一受支持的数据库

此方法失败 DatabaseError: Execution failed on sql 'SELECT name FROM sqlite_master WHERE type='table' AND name=?;': not all arguments converted during string formatting

import snowflake

conn = snowflake.connector.connect(
    account=acct,
    warehouse=wh,
    database=db,
    schema=sc,
    user=usr,
    private_key=pkb,
)

df.to_sql('TABLENAME', con=conn, if_exists='replace', index=False)

方法 2 - SQLAlchemy 引擎

我找到了关于如何在 SQLAlchemy 中使用私钥的文档。但是,它在调用 engine.connect()...

时失败并显示 ValueError: Invalid IPv6 URL
from snowflake.sqlalchemy import URL
from sqlalchemy import create_engine

engine = create_engine(URL(
    account=acct,
    warehouse=wh,
    database=db,
    schema=sc,
    user=usr,
    connect_args={
        'private_key': pkb,
    }
))

with engine.connect() as conn:
    df.to_sql('TABLENAME', con=conn, if_exists='replace', index=False)

这两个错误的回溯都很长,但如果有助于解决问题,我很乐意 post 它们。

我不知道 #2 有什么问题,但我发现结合 #1 和 #2 会起作用...

import snowflake.connector
from sqlalchemy import create_engine

conn = snowflake.connector.connect(
    account=acct,
    warehouse=wh,
    database=db,
    schema=sc,
    user=usr,
    private_key=pkb,
)

engine = create_engine(f"snowflake://{acct}.snowflakecomputing.com", creator=lambda: conn)

try:
    with engine.connect() as c:
        # Note: the table name MUST be all lowercase for some reason, even though Snowflake uses all caps
        df.to_sql('TABLENAME'.lower(), con=c, if_exists='replace', index=False)
finally:
    engine.dispose()
    conn.close()

#2 的问题是您错过了闭包。 connect_argssqlalchemy.crate_engine 调用的一部分,而不是 snowflake.sqlalchemy.URL 调用的一部分。

更正代码(如 snowflake-sqlalchemy GitHub README 中所述):

engine = create_engine(URL(
    account=acct,
    warehouse=wh,
    database=db,
    schema=sc,
    user=usr,
    ),
    connect_args={
        'private_key': pkb,
    }
)