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_args
是 sqlalchemy.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,
}
)
我的目标是能够使用 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_args
是 sqlalchemy.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,
}
)