Я загрузка шейпа в базу данных PostGIS с использованием shp2pgsql, по конвейеру через PSQL, завернутый в питоне подпроцесса, как это:Невозможно установить psycopg2 AutoCommit после импорта shp2pgsql
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
эквивалентны.
Затем я хочу установить con.autocommit = True
для подключения psycopg2 к одной базе данных. Я получаю следующую ошибку:
psycopg2.ProgrammingError: autocommit cannot be used inside a transaction
Почему psycopg2 сообщает, что транзакция все еще продолжается? Есть ли другой способ закрыть транзакцию psql?
Если я не запустил команду subprocess shp2pgsql, con.autocommit
будет успешно выполнен. По умолчанию shp2pgsql оставляет транзакцию открытой? (http://www.bostongis.com/pgsql2shp_shp2pgsql_quickguide.bqg не рекомендует это делать)
В pg_locks
не существует соответствующих статей, чтобы предлагать сделку с остановкой/бездействием. Я не использую объект соединения psycopg2 в функции shp2pgsql. И, если я воссоздать новый объект подключения
con = psycopg2.connect(host=db_host, user=db_user, password=db_pass, database=db_name)
после функции shp2pgsql, con.autocommit=True
работает отлично.
Редактировать: Я, конечно, могу просто создать объект подключения psycopg2 после завершения импорта shp2pgsql, но это не идеально для моего кода, и я бы лучше понял, что происходит.
Edit2: установка con.autocommit=True
сразу после открытия соединения psycopg2, в отличие от более позднего, обходит эту ошибку.
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)
Не могли бы вы разместить MWE для этого? Я хочу быть уверенным, что я понимаю, как излагается код. – Richard
Я добавил MWE выше в исходное сообщение. –