我的Colleauge为我写了python函数,用于将数据从服务器上的文件导入postgresql db。
基本上它使用“COPY”将数据加载到我现有的表中。
当我从查询窗口(pgAdmin)调用包装器plpythonu函数时,它几乎立即完成(小测试数据),并正确加载数据。 但是当我尝试从我的其他函数(plpgsql)中调用它时,它就会挂起。
当查看pg_stat_activity时,会在那里显示COPY命令,其中state ='active'且waiting ='t'。 在python函数中,我们尝试使用set_isolation_level进行自动提交,我们也尝试了显式提交。我们还尝试了一个简单的硬编码INSERT而不是COPY,但它的行为方式相同。
有什么我们不知道或遗忘的东西吗?我尝试在谷歌搜索类似的主题,到目前为止无济于事。
编辑 - 添加了代码,由于显而易见的原因,一些部分被遗漏了。 首先是“主要”python脚本:
import os
import subprocess
import psycopg2
import psycopg2.extensions
_DB_HOST = # left out
_DB_NAME = # left out
_DB_USER = # left out
_DB_PWD = # left out
#-----------------------------------------------------------------------------------------------------------------------
def _copyFile(cur, filePath):
# it was tried with "COPY ... , for testing I use a simpler hardcoded insert
cmd = "insert into etl.tmp_import_file(file_line) values('test insert from python ' || clock_timestamp());"
# table etl.tmp_import_file exists, column file_line is varchar(100), and it works when the plpythonu function is called by itself
cur.execute(cmd)
#-----------------------------------------------------------------------------------------------------------------------
def save_file(fileId):
dbc = psycopg2.connect(database=_DB_NAME, user=_DB_USER, host=_DB_HOST, password=_DB_PWD)
# dbc.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT) # didn't work either
cur = dbc.cursor()
_copyFile(cur, filePath)
dbc.commit()
dbc.close()
#-----------------------------------------------------------------------------------------------------------------------
if __name__ == "__main__":
import sys
if len(sys.argv) < 2:
print 'Usage: save_file.py <file_id>'
sys.exit(1)
else:
save_file(sys.argv[1])
sys.exit(0)
这是pg server中的“包装器”plpythonu函数:
CREATE OR REPLACE FUNCTION etl.save_file(file_id integer)
RETURNS integer AS
$BODY$
import sys
sys.path.append("/path_to_the_python_script")
import test_save_file as c
try:
c.save_file(file_id)
return 0
except:
return -1
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
ALTER FUNCTION etl.save_file(integer)
OWNER TO postgres;