我有三个安装了cx_Oracle和Oracle Instantclient的Python Anaconda环境。我正在使用conda
提供似乎运行良好的虚拟环境,并且正在使用Oracle Wallet向系统提供实际的凭证。请注意,这些环境不会并且永远不会安装SQL * Plus,因为它们仅是为了通过更高的抽象度(例如Python或Java)与数据库进行通信。
我遇到的麻烦来自三种环境中的两种。执行以下Python脚本时,连接仅可在三种环境之一中正常工作。请注意,标识符在各个环境中都不同,但大致相同。
import cx_Oracle
import os
os.environ['TNS_ADMIN'] = '/data/config/wallets/app'
conn = cx_Oracle.connect('/@ENV_CONNECTION')
当我在一个环境中执行此操作时,会得到一个预期的游标实例,并且一切正常。在另外两个上,我看到了:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cx_Oracle.DatabaseError: ORA-12162: TNS:net service name is incorrectly specified
我已经 个五元组检查了 ,服务名称和钱包本身。有一个Java应用程序也在使用此钱包,如果该钱包被认为是坏的,它将无法连接,因此原则上不予考虑。
唯一剩下的未知数是如何引用钱包本身。
我如何反思cx_Oracle如何引用我的TNS_ADMIN位置并提取正确的目录?我觉得如果我能弄清楚,其余的我就能解决。
我所处环境的条件:
答案 0 :(得分:1)
检查cx_Oracle传递给较低层(例如Oracle Net)的最简单方法可能是扩展Connection类并添加您自己的日志记录。基类为cx_Oracle.Connection
,请参见示例https://github.com/oracle/python-cx_Oracle/blob/master/samples/Subclassing.py
您可以运行strace或类似工具来查看正在打开哪些Oracle配置文件(例如tnsnames.ora)。
可以启用Oracle Net跟踪,请参见ADR Diagnostic Parameters in sqlnet.ora。为了进行简单的跟踪,我通常创建一个文件“〜/ .sqlnet.ora”,其内容如下:
TRACE_LEVEL_CLIENT = USER
ADR_BASE=/tmp
然后运行该应用程序,并在创建的/tmp/oradiag_*
目录中深入到*.trc
文件。
答案 1 :(得分:0)
克里斯托弗·琼斯(Christopher Jones)的回答使我获得了救赎,但现实情况是问题远不止于此。
我结束了在两台计算机的主目录中创建sqlnet.ora
文件的工作-一台可以工作,另一台不能工作。我注意到了日志文件的显着差异。
“好”框有以下条目:
2018-07-06 09:59:36.726 : nnftrne:Using tnsnames.ora address (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521)) (CONNECT_DATA = (SID = my_sid))) for name ENV_CONNECTION
“错误”框中输入以下内容:
2018-07-06 10:02:12.879 : nnftrne:Using tnsnames.ora address (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521 for name ENV_CONNECTION
这个伤口转化为我曾经遇到过的最愚蠢,最令人惊讶的空白限制。
请记住,Java中也使用了所使用的钱包(及其对应的tnsnames.ora文件)。我的假设是,从共享资源中读取Python和Java时,它们的行为类似,因为它们会在必要时忽略换行符和空格。
我显然是错的。
“好”框中的条目如下所示:
ENV_CONNECTION =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521))
(CONNECT_DATA =
(SID = my_sid)
)
)
“错误”框中的条目如下所示:
ENV_CONNECTION =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = my.oracle.db.host)(PORT = 1521
))
(CONNECT_DATA =
(SID = my_sid)
)
)
差异足够细微,但对于Python来说是显而易见的:如果tnsnames.ora文件的格式不正确,则cx_Oracle将失败进行解析,而Java是 fine 与此。
感觉上像是一个错误,但修复格式后允许Python重新连接。