Python shp2pgsql导入后无法设置psycopg2自动提交
我正在使用shp2pgsql将shapefile加载到postGIS数据库中,通过psql管道传输,包装在python子流程中,如下所示:Python shp2pgsql导入后无法设置psycopg2自动提交,python,postgresql,psycopg2,psql,Python,Postgresql,Psycopg2,Psql,我正在使用shp2pgsql将shapefile加载到postGIS数据库中,通过psql管道传输,包装在python子流程中,如下所示: command = "shp2pgsql -s 4269 -a -D -W LATIN1 file.shp table | psql -h host -d db -U user" p=subprocess.Popen(command, shell=True) p.communicate() 这一点非常有效,具有以下输出: Loading objects..
command = "shp2pgsql -s 4269 -a -D -W LATIN1 file.shp table | psql -h host -d db -U user"
p=subprocess.Popen(command, shell=True)
p.communicate()
这一点非常有效,具有以下输出:
Loading objects...
Shapefile type: Polygon
Postgis type: MULTIPOLYGON[2]
SET
SET
BEGIN
COMMIT
没有END
语句,但据我所知END
和COMMIT
是等效的
然后,我想为到同一数据库的psycopg2连接设置con.autocommit=True
。我得到以下错误:
psycopg2.ProgrammingError: autocommit cannot be used inside a transaction
为什么psycopg2报告事务仍在进行中?是否有其他方法可以关闭psql事务
如果我没有运行shp2pgsql子流程命令,con.autocommit
将成功执行。shp2pgsql默认情况下是否在某个地方保留打开的事务?(不建议这样做)
pg_locks
中不存在相关条目来建议暂停/空闲事务。我没有在shp2pgsql函数中使用psycopg2连接对象。如果我重新创建一个新的连接对象
con = psycopg2.connect(host=db_host, user=db_user, password=db_pass, database=db_name)
在shp2pgsql函数之后,con.autocommit=True
工作正常
编辑:我当然可以在所有shp2pgsql导入完成后创建psycopg2连接对象,但这在我的代码中并不理想,我更希望了解发生了什么
Edit2:在打开psycopg2连接后立即设置con.autocommit=True
,而不是稍后设置,会绕过此错误
Edit3:添加MWE
import psycopg2
import os
import subprocess
from glob import glob
def vacuum(con, table=""):
autocommit_orig = con.autocommit
con.autocommit = True
with con.cursor() as cur:
cur.execute("VACUUM ANALYZE {};".format(table))
con.autocommit = autocommit_orig
def read_shapefile(path, tablename, srid="4269"):
command = "shp2pgsql -s {} -a -D -W LATIN1 {} {} | psql -h {} -d {} -U {}".format(srid, path, tablename, host, dbname, user)
p=subprocess.Popen(command, shell=True)
p.communicate()
def load_data(con, datapath):
dir = os.path.join(datapath,dataname)
shapefiles = glob(os.path.join(dir,"*.shp"))
for shapefile in shapefiles:
read_shapefile(shapefile, tablename)
if __name__ == "__main__":
con = psycopg2.connect(host=db_host, user=db_user, password=db_pass, database=db_name)
load_data(con, datapath)
vacuum(con, tablename)
我看不出这是在哪里发生的,但是根据,和,事务在第一次向数据库发送命令时开始 事务是每个连接的,因此
psql
不应该让您感到困惑
接下来,我的建议是在代码中的con.autocommit=True
之前粘贴一个con.rollback()
。这将结束以某种方式启动的隐式事务。如果您仍然拥有所需的所有数据,则会发出SELECT
命令或类似的只读指令
如果从con.autocommit=True
向后移动con.rollback()
,它将允许您隔离事务开始的位置,而无需重新构造代码
这是一个猜测,但当
psql
更改数据库状态时,psycopg2是否会在此时开始事务?我还没有找到支持这一假设的文档。我看不出这是在什么地方发生的,但根据和,事务在第一次向数据库发送命令时就开始了
事务是每个连接的,因此psql
不应该让您感到困惑
接下来,我的建议是在代码中的con.autocommit=True
之前粘贴一个con.rollback()
。这将结束以某种方式启动的隐式事务。如果您仍然拥有所需的所有数据,则会发出SELECT
命令或类似的只读指令
如果从con.autocommit=True
向后移动con.rollback()
,它将允许您隔离事务开始的位置,而无需重新构造代码
这是一个猜测,但当
psql
更改数据库状态时,psycopg2是否会在此时开始事务?我还没有找到支持这一假设的文档。只是添加了一些额外的信息,这些信息是我刚才遇到类似问题时发现的
我试着这么做:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
使用conn,conn.cursor()作为cur:
当前执行(“”)
创建数据库mydb;
将数据库mydb上的所有权限授予myuser;
""")
然而,我不断得到:psycopg2.InternalError:创建数据库无法在事务块内运行
我尝试了各种方法:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
conn.set_会话(autocommit=True)
连接设置隔离级别(psycopg2.extensions.isolation级别自动提交)
…他们都还是犯了错误
原来问题是试图同时执行两条语句
这起到了作用:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
使用conn,conn.cursor()作为cur:
cur.execute(“创建数据库mydb”)
cur.execute(“将数据库mydb上的所有权限授予myuser”)
只是添加了一些额外的信息,这些信息是我刚才遇到类似问题时发现的
我试着这么做:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
使用conn,conn.cursor()作为cur:
当前执行(“”)
创建数据库mydb;
将数据库mydb上的所有权限授予myuser;
""")
然而,我不断得到:psycopg2.InternalError:创建数据库无法在事务块内运行
我尝试了各种方法:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
conn.set_会话(autocommit=True)
连接设置隔离级别(psycopg2.extensions.isolation级别自动提交)
…他们都还是犯了错误
原来问题是试图同时执行两条语句
这起到了作用:
conn=psycopg2.connect(数据库URL)
conn.autocommit=True
使用conn,conn.cursor()作为cur:
cur.execute(“创建数据库mydb”)
cur.execute(“将数据库mydb上的所有权限授予myuser”)
您可以为此发布MWE吗?我想确定我了解代码的布局。我已经在原始帖子中添加了一个MWE。你能为此发布一个MWE吗?我想确保我理解代码是如何布局的。我在原始帖子中添加了一个MWE。