Python SQL*Plus 子进程错误:sgslunUDPNew:无法创建通信端点

Posted

技术标签:

【中文标题】Python SQL*Plus 子进程错误:sgslunUDPNew:无法创建通信端点【英文标题】:Python SQL*Plus subprocess Error: sgslunUDPNew: Unable to create communication endpoint 【发布时间】:2020-10-16 13:54:05 【问题描述】:

所以我们使用 python 和 sqlplus 将所有表导出到 csv 文件。由于我们的 oracle 数据库中有一些 unicode 数据,我们需要将 NLS_LANG 环境变量设置为 .AL32UTF8 以便 sqlplus 在后台处理到 csv 文件时实际使用 utf-8 编码。

手动执行此操作并在 cmd 中设置 NLS_LANG 变量可以正常工作。

然而下面的python sn -p:

...

print("Connecting to database ...")
with subprocess.Popen(["C.\\My\\Path\\To\\sqlplus.exe", "MyUser/MyPassword@whocares.com:1522/MyDataBase"], stdin=subprocess.PIPE, encoding='utf-8', env="NLS_LANG": ".AL32UTF8") as p:
    p.stdin.write("set echo off newpage 0 pagesize 0 linesize 3000 feed off head off trimspool on \n")
    p.stdin.flush()

...

导致 sqlplus 失败并出现此错误:

SQL*Plus: Release 19.0.0.0.0 - Production on Fri Oct 16 15:24:37 2020
Version 19.8.0.0.0

Copyright (c) 1982, 2020, Oracle.  All rights reserved.

sgslunUDPNew: Unable to create communication endpoint
ERROR:
ORA-12154: TNS:could not resolve the connect identifier specified

在打开子进程时省略环境变量但效果很好:

...


print("Connecting to database ...")
with subprocess.Popen(["C.\\My\\Path\\To\\sqlplus.exe", "MyUser/MyPassword@whocares.com:1522/MyDataBase"], stdin=subprocess.PIPE, encoding='utf-8') as p:
    p.stdin.write("set echo off newpage 0 pagesize 0 linesize 3000 feed off head off trimspool on \n")
    p.stdin.flush()

...

更有趣的是,我们设置哪个环境变量并不重要。但是,一旦我们将 any 环境变量传递给 python 中的 sqlplus 子进程,它就会崩溃。

我们不确定这是否与 python 或 sqlplus 或两者的组合有关,任何帮助将不胜感激。

就版本而言,我们使用Windows 10SQL*Plus: Release 19.0.0.0.0 - Production Version 19.8.0.0.0Python 3.8.5

【问题讨论】:

这看起来很老套——正如您发现的那样容易出错。硬编码密码本身就是一个很大的危险信号。为什么必须从 Python 调用 SQL*Plus? SQL*Plus 和 Python 都支持 CSV。请参阅 blogs.oracle.com/opal/… 和 docs.python.org/3/library/csv.html 我个人会使用 Oracle 的 cx_Oracle 接口仅在 Python 中导出,因为 Python 具有更好的流控制和文件管理。 首先感谢您提供的链接。我会在星期一调查他们。上面的代码很糟糕而且毫无疑问,我们肯定会找到一种不同的方法来解决它:D 然而,这个堆栈溢出问题主要是因为我们被这个糟糕的 python 子进程解决方案不起作用所震惊。因此,我们主要寻找why 而不是how else。也许有人以前经历过与 python 子处理类似的事情,并且可以对这个奇怪的错误提供一些见解 【参考方案1】:

好的 - 稍微测试一下并让它工作

import subprocess, os

line = "SCOTT/tiger@xxx.xxx.xxx.xxx:yyyyy/sssss"    

# fails
# subprocess.run(["sqlplus.exe", line], env="NLS_LANG": ".AL32UTF8")

my_env = os.environ.copy()
my_env["NLS_LANG"] = ".AL32UTF8"

# works
# subprocess.run(["sqlplus.exe", line], env=my_env)

#adopting solution
print("Connecting to database ...")
with subprocess.Popen(["C:\\ORACLE\\IC\\12201\\instantclient_12_2\\sqlplus.exe", "SCOTT/tiger@xxx.xxx.xxx.xxx:yyyyy/sssss"], stdin=subprocess.PIPE, encoding='utf-8', env=my_env) as p:
    p.stdin.write("set echo off newpage 0 pagesize 0 linesize 3000 feed off head off trimspool on \n")
    p.stdin.flush()

输出

Connecting to database ...

SQL*Plus: Release 12.2.0.1.0 Production on Sun Oct 18 00:07:22 2020

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Last Successful login time: Sun Oct 18 2020 00:04:57 +02:00

Connected to:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics
and Real Application Testing options

SQL> SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Advanced Analytics
and Real Application Testing options

最后使用 NLS_LANG 没有问题,因为即使是类似的东西

subprocess.run(["sqlplus.exe", line], env="A": "1")

失败 - 您只需要创建一个有效的环境,例如

my_env = os.environ.copy()
my_env["NLS_LANG"] = ".AL32UTF8"

并将其分配给like中的“env”

with subprocess.Popen( ..... , env=my_env)

弗兰克

【讨论】:

【参考方案2】:

sgslunUDPNew:无法创建通信端点 错误: ORA-12154: 意味着 Oracle 网络层 (TNS) 尝试使用 OS 网络库打开无效或禁止的端口 - 这可能是包含该端口的格式错误或编码错误的字符串的结果 - 最后 TNS 报告传递给 SQL* 的错误加号

所以 - 由于 SQLPLUS 可以启动,这提供了测试的机会

with subprocess.Popen(["C.\My\Path\To\sqlplus.exe

请看看您使用 Unicode 会遇到哪些“不错”的结果 - 这是我一周前发现的。最后,我相信 SQL*Plus 可能无法在内部正确解码 unicode。将测试这些东西。

How to connect to database using QOCI or QODBC with correct encoding?

无论如何 - 要获得通用性,请考虑将 pyODBC 与 Oracle ODBC 驱动程序一起使用,该驱动程序已获得官方支持 - 或其他数据库的其他 ODBC

【讨论】:

以上是关于Python SQL*Plus 子进程错误:sgslunUDPNew:无法创建通信端点的主要内容,如果未能解决你的问题,请参考以下文章

如何使操作系统命令的标准错误以“!”运行转到 Sql*plus 线轴?

Python3.5子进程错误

Python 子进程返回错误的退出代码

python 3子进程错误以字节为单位

带有变量的python子进程check_output中的错误

尝试在python子进程中运行rsync时出现意外的远程arg错误