Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python shp2pgsql导入后无法设置psycopg2自动提交_Python_Postgresql_Psycopg2_Psql - Fatal编程技术网

Python shp2pgsql导入后无法设置psycopg2自动提交

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..

我正在使用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...
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。