【问题标题】:Execute psql command from python script从 python 脚本执行 psql 命令
【发布时间】:2020-04-15 09:23:55
【问题描述】:

我可以通过什么方式从 Python 脚本执行 psql 命令?我的代码从 PostgreSQL 数据库插入和更新数据(使用 psycopg2 和游标方法)。当我执行像

这样的查询时,它工作正常
cursor.execute("UPDATE Segment set idcurve = %s where id = %s ", (id_curve, id_segment,))

但是在 psql 的情况下,当我将命令传递给 cursor.execute (see edits to similar question) 时,我得到了 SyntaxError: syntax error at or near "\"。 此外,该命令在 console.sql DataGRIP 中失败(无论如何它都会对所有行执行......)

这个命令是否只能在 shell 中工作(我必须使用 os.system)吗?因为cursor 无法解释?

编辑 尝试使用子进程:

import subprocess

sql = """SELECT uuid IS NULL AS is_uuid FROM dpoint WHERE uuid = '5547f4b7-00b3-4aac-8ceb-c9ca163a0214';
\gset 
\if :is_uuid 
    INSERT INTO DPoint (uuid) VALUES ('5547f4b7-00b3-4aac-8ceb-c9ca163a0214');
    WITH ins1 AS (INSERT INTO Point (latitude, longitude, srid) 
          VALUES (64.44, 28.77, 4326) RETURNING id AS id_point)
    INSERT INTO SPoint (idPoint, uuiddpt) VALUES ((SELECT id_point FROM ins1), '5547f4b7-00b3-4aac-8ceb-c9ca163a0214');
\endif
"""
subprocess.check_call(['psql -h localhost -d dbase -U myuser -W --command={}'.format(sql)], env={'PGPASSWORD': 'mypass'})

抛出OSError: [Errno 36] File name too long

EDIT2

subprocess.check_call(['psql', '-q', '-U', 'myuser', '-h', 'localhost', '-c', '{}'.format(sql), 'dbase'], env={'PGPASSWORD': 'mypass'})

当我拆分查询尝试执行的所有参数时 -> 它以syntax error at or near "\" 失败。 -E(正如 Lu M 建议的那样)没有帮助。它适用于我将查询保存到 .sql 文件但我想以交互方式执行它的情况。

EDIT3

根据章节--command=command 中的psql tutorial,有两个选项可用于混合SQL 和psql 元命令。以什么方式可以将其包装在子流程中? 我都尝试了,但出现了不需要的额外反斜杠,并且它不被识别为一个命令:

subprocess.check_call(['psql', '-q', '-U', 'myuser', '-h', 'localhost',
                   '-c', '{}'.format(sql),
                   '-c', '{}'.format('\gset'),
                   '-c', '{}'.format('\if :is_uuid '),
                   '-c', '{}'.format(sql2),
                   '-c', '{}'.format('\endif'), 'dbase'],
                  env={'PGPASSWORD': 'mypass'})

unrecognized value ":is_uuid" for "\if expression": Boolean expected 失败

【问题讨论】:

  • ` are, as you already guessed, psql`命令开头的命令,不是由DBMS本身解释,而是由psql程序解释。
  • @stickybit 这个答案stackoverflow.com/a/19930714/8129993 仍然有效并且是最新的吗?
  • 好吧,你为什么不试试看它是否适合你?
  • 我正在尝试,但没有成功(请参阅我的问题的编辑)
  • 理论上你可以重写它以使用常规 sql,但我不确定它应该做什么。第一个查询要么不返回任何内容,要么返回 false。

标签: python sql postgresql subprocess psql


【解决方案1】:

您似乎正试图通过类似于this question 的 psycopg2 运行Meta-Command。 Psycopg2 无法处理元命令,这就是它抛出此语法错误的原因。

this question 的以下内容可能适用于您的情况:

正如@piro 在评论中所写的那样,命令行 psql -E 将回显用于实现 \d 和其他反斜杠命令(无论何时在 psql 提示符中使用其中一个命令)的 SQL 查询,这确实是一个重要信息。这样你就很容易得到你想要的。

编辑:否则你将不得不使用子进程,正如 cmets 已经指出的那样。

【讨论】:

  • 感谢您的回答!我正在尝试您的两个想法(请参阅我的编辑),但没有成功(
  • 我现在很忙,但是如果问题仍然存在,我会看看我是否可以找到在子进程中运行元命令的解决方案。也许尝试将整个命令存储在一个 txt 文件中并阅读它?
  • 我试图将我的命令保存到 .sql 文件。它可以工作,但我想以交互方式执行它
  • 现在只是一个 hack,但理论上你总是可以生成文件,然后通过子进程调用它。
  • 序列化/反序列化是一个高负载操作,不是吗?我必须处理很多对象...此外,我已经使用 uuid 等硬编码值进行了测试。实际上它们是从脚本参数化的(生成查询的方法是什么?根据initd.org/psycopg/docs/… 正确的方法是通过传递变量执行sql)
猜你喜欢
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多