Python 如何跟踪cx_Oracle试图连接到数据库的方式?

Python 如何跟踪cx_Oracle试图连接到数据库的方式?,python,conda,cx-oracle,Python,Conda,Cx Oracle,我有三个Python Anaconda环境,其中安装了cx_Oracle和Oracle的Instantclient。我正在使用conda来提供虚拟环境,它似乎工作正常,我正在使用Oracle Wallet向系统提供实际凭证。请注意,这些环境没有也永远不会安装SQL*Plus,因为它们只是通过更高的抽象(例如Python或Java)与数据库通信 我遇到的麻烦来自三种环境中的两种。在执行以下Python脚本时,连接仅适用于三种环境中的一种。请注意,标识符在不同环境中是不同的,但大致相同 import

我有三个Python Anaconda环境,其中安装了cx_Oracle和Oracle的Instantclient。我正在使用
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
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
cx_Oracle.DatabaseError:ORA-12162:TNS:net服务名称指定不正确
我已经检查了服务名称和钱包本身。有一个Java应用程序也在使用这个钱包,如果钱包被认为是坏的,它将无法连接,所以我原则上排除这种可能性

唯一尚不清楚的是钱包本身是如何被引用的

我如何反思cx_Oracle是如何引用我的TNS_管理位置并将其放入正确的目录的?我觉得如果我能弄明白,我就能解决剩下的问题

我为我的环境所做的:

  • 康达4.4.11
  • instantclient 12.2
  • cx_Oracle版本6.3.1
      • 检查cx_Oracle传递给较低层(例如Oracle Net)的内容的最简单方法可能是扩展连接类并添加您自己的日志记录。基类是
        cx\u Oracle.Connection
        ,请参见示例

      • 您可以运行strace或类似程序,查看正在打开哪些Oracle配置文件,如tnsnames.ora

      • 可以启用Oracle Net跟踪,请参阅。对于一个简单的跟踪,我通常创建一个文件“~/.sqlnet.ora”,其内容如下:
        
        跟踪\级别\客户端=用户
        日均房价基数=/tmp
        
        然后运行应用程序,通过创建的
        /tmp/oradiag.*
        目录深入到
        *.trc
        文件

          • 检查cx_Oracle传递给较低层(例如Oracle Net)的内容的最简单方法可能是扩展连接类并添加您自己的日志记录。基类是
            cx\u Oracle.Connection
            ,请参见示例

          • 您可以运行strace或类似程序,查看正在打开哪些Oracle配置文件,如tnsnames.ora

          • 可以启用Oracle Net跟踪,请参阅。对于一个简单的跟踪,我通常创建一个文件“~/.sqlnet.ora”,其内容如下:
            
            跟踪\级别\客户端=用户
            日均房价基数=/tmp
            
            然后运行应用程序,通过创建的
            /tmp/oradiag.*
            目录深入到
            *.trc
            文件


          克里斯托弗·琼斯的回答让我获得了救赎,但现实是问题远比这微妙

          最后,我在两台机器的主目录中创建了
          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
          
          “坏”框中有以下条目:

          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
          
          这是我遇到过的最愚蠢、最令人惊讶的空白限制之一

          请记住,所使用的钱包(及其对应的tnsnames.ora文件)也在Java中使用。我的假设是,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)
              )
            )
          
          “坏”框中的条目如下所示:

          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对此没有问题


          这本身就是一个bug,但修复格式可以让Python再次连接。

          克里斯托弗·琼斯的回答让我找到了救赎,但现实是问题远比这微妙

          最后,我在两台机器的主目录中创建了
          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
          
          “坏”框中有以下条目:

          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
          
          这是我遇到过的最愚蠢、最令人惊讶的空白限制之一

          请记住,所使用的钱包(及其对应的tnsnames.ora文件)也在Java中使用。我的假设是,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)
              )
            )
          
          “坏”框中的条目如下所示:

          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对此没有问题


          这感觉就像一只虫子,但是修复格式允许Python再次连接。

          您也可以使用sqlplus使用提供给cx_Oracle的连接字符串连接到数据库。您也可以使用sqlplus使用提供给cx_Oracle的连接字符串连接到数据库。我想与Oracle开发团队跟进。你在哪个站台?什么JDBC版本?文件是否有*IX或Windows行终止?@Christophe