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 10
与SQL*Plus: Release 19.0.0.0.0 - Production Version 19.8.0.0.0
和Python 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 线轴?