Python 为什么来自同一sqlalchemy引擎的多个连接会产生不同的信息?
我正在使用PostgreSQL 9.3和SQLAlchemy 1.0.11 我有如下代码:Python 为什么来自同一sqlalchemy引擎的多个连接会产生不同的信息?,python,postgresql,sqlalchemy,temp-tables,Python,Postgresql,Sqlalchemy,Temp Tables,我正在使用PostgreSQL 9.3和SQLAlchemy 1.0.11 我有如下代码: import sqlalchemy as sa engine = sa.create_engine('postgresql+psycopg2://me@myhost/mydb') conn = engine.connect() metadata = sa.MetaData() # Real table has more columns mytable = sa.Table( 'my_temp
import sqlalchemy as sa
engine = sa.create_engine('postgresql+psycopg2://me@myhost/mydb')
conn = engine.connect()
metadata = sa.MetaData()
# Real table has more columns
mytable = sa.Table(
'my_temp_table', metadata,
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('something', sa.String(200)),
prefixes=['TEMPORARY'],
)
metadata.create_all(engine)
pg_conn = engine.raw_connection()
with pg_conn.cursor() as cursor:
cursor.copy_expert('''COPY my_temp_table (id, something)
FROM STDIN WITH CSV''',
open('somecsvfile', 'r'))
现在这一切都很好——cursor.rowcount报告插入的预期行数。我甚至可以运行游标。执行“从我的临时表中选择计数”;printcursor.fetchone,它将显示相同的内容。问题是当我尝试从SQLAlchemy的连接运行查询时,例如
result = conn.execute(sa.text('SELECT count(*) FROM my_temp_table'))
不管我把它放在哪里。我试过几个地方:
在带块的内部
在街区外
在光标之后。关闭
在pg_连接关闭后
似乎什么都不起作用-无论我从何处运行查询,它都会伴随以下内容:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) relation "my_temp_table" does not exist
有趣的是,如果我用try/except包装代码,那么我就可以执行cursor.execute。。。在except块中成功执行
事实上,现在我写出来了,似乎在任何地方使用sqlalchemy连接都看不到这些表的存在
那么是什么原因呢?为什么我的SQLAlchemy连接看不到这些表,而postgres engine.raw_连接看不到这些表
编辑:
为了进一步揭开谜团,如果我在metadata.create_allengine之后创建连接,它就会工作!嗯,有点
我可以从表中选择,但当我获得engine.raw\u连接时,它会失败。复制\u expert,因为它找不到表。好吧,这并不能回答为什么,但它是如何实现我想要的 而不是:
pg_conn = engine.raw_connection()
with pg_conn.cursor() as cursor:
只需将其替换为:
with conn.connection.cursor() as cursor:
通过.connection属性创建SQLAlchemy连接对象。无论其中包含什么魔力,都是正确的。首先要注意的是,临时表只对创建它们的连接可见 第二,引擎不封装单个连接;它管理着一个网络 最后,指出直接在Engine.executeselect上执行的操作。。。在他们的示例中,将在内部获取并释放他们自己的连接 考虑到所有这些,很清楚您的示例中发生了什么: conn=engine.connect从池中获取连接1。 metadata.create_allengine隐式获取连接2,因为从引擎的角度来看,1仍在使用中,使用它创建表,并将其释放回池。 pg_conn=engine.raw_连接再次获取2,因此通过该对象执行的复制仍然可以看到该表。 conn仍在使用1,您通过此对象所做的任何操作都无法查看您的临时表。 在第二种情况下: metadata.create_allengine隐式获取/使用/释放连接1。 conn=engine.connect获取并保持1。 pg_conn=engine.raw_连接获取2,副本无法找到临时表。
这个故事的寓意是:如果你正在做一些依赖于连接状态的事情,你最好确定你正在使用哪个连接。直接在引擎上运行命令对于独立操作来说是很好的,但是对于涉及临时表的任何操作,您都应该获得一个连接,并在包括表创建在内的每一个步骤中坚持使用它,我建议您将其更改为元数据。创建\u allconn。Nice。我甚至都不知道,创造奥尔康是一件事。工作起来像个符咒,而且可能没有那么神奇@韦恩:你们都会接受任何东西。我想这适用于大多数需要数据库连接的事情。有趣的是,我又遇到了同样的问题。未来的我:你现在可能已经忘记了,但你需要使用conn=engine.connect;pg_conn=conn.connection以获取原始连接,因此您可以执行metadata.create_allconn,然后稍后使用原始连接。