【问题标题】:How can I access Oracle from Python?如何从 Python 访问 Oracle?
【发布时间】:2011-04-01 02:30:37
【问题描述】:

如何从 Python 访问 Oracle?我已经下载了一个 cx_Oracle msi 安装程序,但是 Python 无法导入该库。

我收到以下错误:

import cx_Oracle

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    import cx_Oracle
ImportError: DLL load failed: The specified module could not be found.

如果有任何帮助,我将不胜感激。

【问题讨论】:

  • 你下载了哪个cx_Oracle? There are many。另外,您使用的是哪个版本的 Python、哪个版本的 Oracle,以及您使用的是哪个操作系统?
  • cx_Oracle-5.0.2-10g.win32-py26
  • 听起来它可能不会被提取到 Python 用来查找模块的 PATH 中。您是否尝试过使用 easy_install 而不是显式安装它(它可能缺少另一个依赖项)。
  • 这个特定错误意味着 Oracle 客户端 OCI DDL 是针对不同平台编译的。 32 位与 64 位或英特尔与 AMD。

标签: python oracle database-connection cx-oracle


【解决方案1】:

这对我有用。我的 Python 和 Oracle 版本与您的略有不同,但应该采用相同的方法。只需确保 cx_Oracle 二进制安装程序版本与您的 Oracle 客户端和 Python 版本匹配即可。

我的版本:

  • Python 2.7
  • Oracle Instant Client 11G R2
  • cx_Oracle 5.0.4(Unicode、Python 2.7、Oracle 11G)
  • Windows XP SP3

步骤:

  1. 下载 Oracle Instant Client 软件包。我使用了 Instantclient-basic-win32-11.2.0.1.0.zip。解压到 C:\your\path\to\instantclient_11_2
  2. 下载并运行 cx_Oracle 二进制安装程序。我使用了 cx_Oracle-5.0.4-11g-unicode.win32-py2.7.msi。我为所有用户安装了它,并将它指向它在注册表中找到的 Python 2.7 位置。
  3. 通过批处理脚本或在您的应用程序上下文中有意义的任何机制设置 ORACLE_HOME 和 PATH 环境变量,以便它们指向 Oracle Instant Client 目录。请参阅下面的 oracle_python.bat 源代码。我确信必须有一个更优雅的解决方案,但我想尽可能地限制我的系统范围的更改。确保将目标 Oracle Instant Client 目录放在 PATH 的开头(或至少在任何其他 Oracle 客户端目录之前)。现在,我只做命令行的事情,所以我只是在 shell 中运行 oracle_python.bat,然后再运行任何需要 cx_Oracle 的程序。
  4. 运行 regedit 并检查是否在 \HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE 中设置了 NLS_LANG 键。如果是这样,请重命名密钥(我将其更改为 NLS_LANG_OLD)或取消设置。该键只应用作 Oracle 7 客户端的默认 NLS_LANG 值,因此除非您碰巧在其他地方使用 Oracle 7 客户端,否则将其删除是安全的。与往常一样,请务必在进行更改之前备份您的注册表。
  5. 现在,您应该可以在 Python 程序中导入 cx_Oracle。请参阅下面的 oracle_test.py 源代码。请注意,对于我的 cx_Oracle 版本,我必须将连接和 SQL 字符串设置为 Unicode。

来源:oracle_python.bat

@echo off
set ORACLE_HOME=C:\your\path\to\instantclient_11_2
set PATH=%ORACLE_HOME%;%PATH%

来源:oracle_test.py

import cx_Oracle

conn_str = u'user/password@host:port/service'
conn = cx_Oracle.connect(conn_str)
c = conn.cursor()
c.execute(u'select your_col_1, your_col_2 from your_table')
for row in c:
    print row[0], "-", row[1]
conn.close()

可能的问题:

  • “ORA-12705: 无法访问 NLS 数据文件或指定的环境无效” - 我在更改 NLS_LANG 注册表之前遇到了这个问题。
  • "TypeError: argument 1 must be unicode, not str" - 如果您需要将连接字符串设置为 Unicode。
  • "TypeError: Expecting None or a string" - 如果您需要将 SQL 字符串设置为 Unicode。
  • “ImportError:DLL 加载失败:找不到指定的过程。” - 可能表示 cx_Oracle 找不到合适的 Oracle 客户端 DLL。

【讨论】:

  • 只要所有版本号和平台都对齐,有谁知道这是否适用于其他版本(即 3.4?和 64 位)?
  • @TheRedPea 这对我来说适用于 3.5 和 64 位版本。
  • 在尝试导入 cx_Oracle 库时,我仍在努力处理 ImportError: DLL load failed: The specified procedure could not be found.
  • 感谢您的详细说明。非常有帮助!!我的理解是,在安装 cx_oracle 并连接到数据库之前,我需要安装 Oracle 客户端。我正在尝试从我的机​​器连接到我们公司集群中的 Oracle db,但无法安装 cx_oracle,显示此错误消息:distutils.errors.DistutilsSetupError: cannot locate an Oracle software installation。
  • 我真的需要 Oracle 客户端来让这个工作吗?不就是直接JDBC连接那么简单吗?泰。
【解决方案2】:

您可以根据Service NameSID 使用以下任何一种方式。

使用 SID:

import cx_Oracle
dsn_tns = cx_Oracle.makedsn('server', 'port', 'sid')
conn = cx_Oracle.connect(user='username', password='password', dsn=dsn_tns)
c = conn.cursor()
c.execute('select count(*) from TABLE_NAME')
for row in c:
   print(row)
conn.close()

服务名称:

import cx_Oracle
dsn_tns = cx_Oracle.makedsn('server', 'port', service_name='service_name')
conn = cx_Oracle.connect(user='username', password='password', dsn=dsn_tns)
c = conn.cursor()
c.execute('select count(*) from TABLE_NAME')
for row in c:
   print(row)
conn.close()

【讨论】:

    【解决方案3】:

    这是我的代码的样子。它还显示了如何使用字典使用查询参数的示例。它适用于使用 Python 3.6:

    import cx_Oracle
    
    CONN_INFO = {
        'host': 'xxx.xx.xxx.x',
        'port': 12345,
        'user': 'SOME_SCHEMA',
        'psw': 'SECRETE',
        'service': 'service.server.com'
    }
    
    CONN_STR = '{user}/{psw}@{host}:{port}/{service}'.format(**CONN_INFO)
    
    QUERY = '''
        SELECT
            *
        FROM
            USER
        WHERE
            NAME = :name
    '''
    
    
    class DB:
        def __init__(self):
            self.conn = cx_Oracle.connect(CONN_STR)
    
        def query(self, query, params=None):
            cursor = self.conn.cursor()
            result = cursor.execute(query, params).fetchall()
            cursor.close()
            return result
    
    
    db = DB()
    result = db.query(QUERY, {'name': 'happy'})
    

    【讨论】:

      【解决方案4】:

      请注意,如果您使用的是 pandas,您可以通过以下方式访问它:

      import pandas as pd
      import cx_Oracle
      conn= cx_Oracle.connect('username/pwd@host:port/service_name')
      try:
          query = '''
               SELECT * from dual
                   '''
          df = pd.read_sql(con = conn, sql = query)
      finally:
          conn.close()
      df.head()
      

      【讨论】:

        【解决方案5】:
        import cx_Oracle
           dsn_tns = cx_Oracle.makedsn('host', 'port', service_name='give service name') 
           conn = cx_Oracle.connect(user='username', password='password', dsn=dsn_tns) 
           c = conn.cursor()
           c.execute('select count(*) from schema.table_name')
        for row in c:
           print row
        conn.close()
        

        注意:

        1. 如果需要,在 (dsn_tns) 中,在任何参数前放置一个 'r' 以便处理任何特殊字符,例如 '\'。

        2. 如果需要,在 (conn) 中,在任何参数前放置一个 'r' 以寻址任何特殊字符,例如 '\'。例如,如果您的用户名包含“\”,则需要在用户名前放置“r”:user=r'User Name' 或 password=r'password'

        3. 如果要将查询分散到多行,请使用三引号。

        【讨论】:

          【解决方案6】:

          除了 Oracle 即时客户端,您可能还需要安装 Oracle ODAC 组件并将它们的路径放入您的系统路径中。 cx_Oracle 似乎需要访问与它们一起安装的 oci.dll 文件。

          还要检查您是否获得了与您的匹配的正确版本(32 位或 64 位):python、cx_Oracle 和即时客户端版本。

          【讨论】:

            【解决方案7】:

            除了 cx_Oracle,您还需要安装 Oracle 客户端库并正确设置路径以便 cx_Oracle 找到它 - 尝试在“Dependency Walker”(http://www.dependencywalker.com/) 中打开 cx_Oracle DLL 以查看缺少的内容DLL 是。

            【讨论】:

              【解决方案8】:

              确保这两个,它应该工作:-

              1. Python、Oracle Instantclient 和 cx_Oracle 是 32 位的。
              2. 设置环境变量。

              在 Windows 上解决了这个问题,就像一个魅力。

              【讨论】:

              • 这不是故意的,不过不知道是怎么进来的。
              【解决方案9】:

              如果您使用的是 virtualenv,则使用安装程序获取驱动程序并非易事。然后你可以做什么:按照 Devon 的描述安装它。然后从 Python\Lib\site-packages 复制 cx_Oracle.pyd 和 cx_Oracle-XXX.egg-info 文件夹 从您的虚拟环境进入 Lib\site-packages。当然,在这里,架构和版本也很重要。

              【讨论】:

                【解决方案10】:
                import cx_Oracle 
                from sshtunnel import SSHTunnelForwarder
                
                # remote server variables
                remote_ip_address = "<PUBLIC_IP_ADDRESS_OF_DB_SERVER>"
                remote_os_username = "<OS_USERNAME>"
                ssh_private_key = "<PATH_TO_PRIVATE_KEY>"
                
                # Oracle database variables
                database_username = "<DATABASE_USER>"
                database_password = "<DATABASE_USER_PASSWORD>"
                database_server_sid = "<ORACLE_SID>"
                
                def server_connection():
                
                    server = SSHTunnelForwarder(
                             remote_ip_address,
                             ssh_username=remote_os_username,
                             ssh_password=ssh_private_key,
                             remote_bind_address=('localhost', 1521) # default Oracle DB port
                    )
                    return server
                
                def database_connection():
                
                    data_source_name = cx_Oracle.makedsn("localhost",
                                                         server.local_bind_port,
                                                         service_name=database_server_sid)
                
                    connection = cx_Oracle.connect(database_username,
                                                   database_password,
                                                   data_source_name, 
                                                   mode=cx_Oracle.SYSDBA) # If logging in with SYSDBA privs,
                                                                          # leave out if not.
                    return connection
                
                def database_execute():
                
                    connection = database_connection()
                
                    cursor = connection.cursor()
                    
                    for row in cursor.execute("SELECT * FROM HELLO_WORLD_TABLE"):
                        print(row)
                    
                if __name__ == '__main__':
                
                    server = server_connection()
                    server.start()                      # start remote server connection
                
                    connection = database_connection()  # create Oracle database connection
                
                    database_execute()                  # execute query
                
                    connection.close()                  # close Oracle database connection
                    server.stop()                       # close remote server connection
                

                如果你通过堡垒隧道访问Oracle数据库,你只需要修改这段代码:

                def server_connection():
                
                server = SSHTunnelForwarder(
                         remote_ip_address, # public IP of bastion server
                         ssh_username=remote_os_username,
                         ssh_password=ssh_private_key,
                         remote_bind_address=('localhost', 1521),
                         local_bind_address=('0.0.0.0', 3333) # Suppose local bind is '3333'
                )
                return server
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2019-07-29
                  • 2021-10-16
                  • 2020-02-19
                  • 2014-07-30
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-07-08
                  相关资源
                  最近更新 更多