使用cx_Oracle连接Python与Oracle的问题

想用Python提取本机Oracle数据库中,#cscott用户下的emp数据表,执行如下程序:

import pandas as pd
import cx_Oracle
import os

#设置环境编码方式,可解决读取数据库乱码问题
os.environ['NLS_LANG'] = 'SIMPLIFIED CHINESE_CHINA.UTF8'

#实现查询并返回dataframe
#使用query(数据表名称)获取数据表:
#获取本地IP
#import socket
#localhost = socket.gethostbyname(socket.gethostname())
def query(table):
    host = "localhost"    #数据库ip 非C:\app\413022472\product\12.2.0\dbhome_1\network\admin\litsener.ora中的HOST(机器名)
    port = "1521"     #端口
    sid = "orcl"    #数据库名称 登陆sqlplus,输入select instance_name from v$instance;可获取
    dsn = cx_Oracle.makedsn(host, port, sid)

    #scott是数据用户名,tiger是登录密码(默认用户名和密码)
    conn = cx_Oracle.connect("c##scott", "tiger", dsn)  

    #SQL语句,可以定制,实现灵活查询
    sql = 'select * from '+ table 

    # 使用pandas的read_sql函数,可以直接将数据存放在dataframe中
    results = pd.read_sql(sql,conn) 

    conn.close
    return results

test_data = query("emp") # 可以得到结果集

执行到conn = cx_Oracle.connect("c##scott", "tiger", dsn)会报错:DatabaseError: ORA-12505: TNS: 监听程序当前无法识别连接描述符中所给出的 SID

listner.ora文档内容如下:

# listener.ora Network Configuration File: C:\app\413022472\product\12.2.0\dbhome_1\network\admin\listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = CLRExtProc)
      (ORACLE_HOME = C:\app\413022472\product\12.2.0\dbhome_1)
      (PROGRAM = extproc)
      (ENVS = "EXTPROC_DLLS=ONLY:C:\app\413022472\product\12.2.0\dbhome_1\bin\oraclr12.dll")
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = DESKTOP-2RE9AJU.lan)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )
  

通过sqlplus的select instance_name from v$instance;也确定过sid的名称正确无误:
图片描述

请问是哪里出错了?如何解决?

阅读 6.2k
1 个回答

老哥首先你的SID没有问题 ,排查思路:

  1. 你检查的是你的tnsname.ora,这个;连接文件 ,然后测试 在cmd 里正常用监听登录是否可以登录

2.我是昨天研究的 ,你的pandas 学习了 pd.read_sql(sql,conn) 这个写法待验证 ,是我get 到的点

3.我遇到的问题是在ubuntu用pycharm里写代码无法连接oracle数据库 ,但pycharm 自带的工具可以连接,在shell里也可以正常连接 最后也没有找到原因 一直报错说是不是64位客户端 ,但我所有的包都是64位的,待解决。。。

4.最后附上干货,我的连接demo 以及将数据写入到csv文件,仅供参考,老哥记得回复我,维护社区秩序。。

#!/usr/bin/python

import cx_Oracle as oracle
import csv
def oraclesql(cursor):
   #fp = open('D:/1.sql')
   #fp_sql = fp.read()
   cursor.execute("select * from emp")
   data = cursor.fetchall()
   #print (list(data))
   return list(data)
def write_to_csv(content):
    with open('oracle.csv','a') as csvfile:
        filename = ['empno','ename','job','mgr','hiredate','sal','comm','deptno']
        #filename = ['LOTS','ORG_ID','YEAR_TIME','NAME_PATIENT','GENDER','BIRTHDAY','AGE','RESIDENT_ID','HUKOU_ADDRESS']
        write = csv.writer(csvfile,delimiter=',')
        # write.writeheader()
        
        write.writerows([content])

 
 
if __name__ == '__main__':
   ipaddr = "127.0.0.1"
   username = "scott"
   password = "scott"
   oracle_port = "1521"
   oracle_service = "orcl"
   try:
      db = oracle.connect(username+"/"+password+"@"+ipaddr+":"+oracle_port+"/"+oracle_service)
    # 将异常捕捉
   except Exception as e:  
      print(e)
   else:
      cursor = db.cursor()
      data = oraclesql(cursor)
      for i in data:
          text = list(i)
          #print(text)
          write_to_csv(text)
      cursor.close()
      db.close()
      
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题