2013-01-09 12 views
15

Sto riscontrando un problema nell'inserimento di unicode in uno schema Oracle, penso che il database sia un'istanza di Oracle 11g ma non sono sicuro a questo punto. Sto usando python 2.6.1 su OS X 10.6.8 (questa è la versione di sistema di python) e sto usando il modulo del driver cx-Oracle versione 5.1 scaricato da sourceforge.net, compilato e installato su un'istanza virtualenv 1.6.1 con i pacchetti del sito visibili. Il mio script è il seguenteImpossibile inserire Unicode utilizzando cx-Oracle

import cx_Oracle 

    connection = cx_Oracle.connect(
     "<name>/<password>@<host>/<service-name>" 
    ) 
    cursor = connection.cursor() 
    result = cursor.execute(u"create table UNICODE_TEST (id NUMBER(6), text NCLOB not NULL)") 

    raw_text = open("test.txt",'r').read() 
    if isinstance(raw_text,str): 
     raw_text = raw_text.decode("utf_8") 

    statement = u"insert into UNICODE_TEST (id, text) values (1,'%s')" % raw_text 
    result = cursor.execute(statement) 

creo una connessione, creare il cursore, eseguire uno statment per creare una tabella di test con un campo id e il testo dei tipi di numero e NCLOB. Apro un file contenente quello che so essere codificato in formato testo in UTF-8, decodificare la stringa in unicode. Creare una dichiarazione di inserimento in una stringa unicode ed eseguire tale istruzione e il risultato è questo errore.

Traceback (most recent call last): 
    File "unicode-test.py", line 19, in <module> 
     result = cursor.execute(statement) 
    UnicodeEncodeError: 'ascii' codec can't encode character u'\u2122' in position 170: ordinal not in range(128) 

Qualcosa sta cercando di codificare la mia dichiarazione come ASCII prima di inserirlo nello schema Oracle. Così ho iniziato a caccia in giro a cercare di capire meglio come cx-Oracle gestisce unicode e trovato questo nel HISTORY.txt della sorgente cx-Oracle ho scaricato da sourceforge.net

modifiche da 5.0.4 a 5.1
1) Rimuovere il supporto per la modalità UNICODE e consentire il passaggio di Unicode in ovunque venga inoltrata una stringa. Ciò significa che le stringhe saranno passate da a Oracle utilizzando il valore della variabile ambiente in Python 3.x anche. In questo modo sono stati eliminati alcuni problemi rilevati utilizzando la modalità UNICODE e rimosso anche una limitazione non necessaria in Python 2.x che non è possibile utilizzare Unicode nelle stringhe di connessione o istruzioni SQL, ad esempio. ...

La mia ipotesi è che la variabile d'ambiente NLS_LANG è impostato su 'ascii' o qualche equivalente, in modo da provare a impostare NLS_LANG a 'AL32UTF8' che credo sia il valore corretto per unicode, e impostare il nuovo valore prima di creare la mia connessione.

os.environ["NLS_LANG"] = "AL32UTF8" 
    connection = cx_Oracle.connect(
     "<user>/<password>@<host>/<service-name>" 
    ) 
    cursor = connection.cursor() 
    ... 

Ma ho ricevuto questo errore.

Traceback (most recent call last): 
    File "unicode-test.py", line 11, in <module> 
     "<user>/<password>@<host>/<service-name>" 
    cx_Oracle.DatabaseError: ORA-12705: Cannot access NLS data files or invalid environment specified 

Quindi sembra che non sia possibile manomettere il valore NLS_LANG.

Ecco le mie domande fin d'ora. Mi manca qualcosa di semplice come un tipo di colonna errato? Il problema con il driver cx-Oracle è? Devo impostare la variabile di ambiente "WITH_UNICODE" quando creo il modulo cx-Oracle e come dovrei farlo? Il problema è con l'istanza di Oracle? Ho poca esperienza con Oracle e non ho mai lavorato con Oracle e Python insieme. Ho trascorso due giorni a lavorare su questo problema e vorrei una migliore comprensione di quale sia il problema prima di andare al gruppo DBA con.

Grazie,

risposta

14

Impostazione variabile d'ambiente è il modo giusto, ma "AL32UTF8" non è il valore giusto per NLS_LANG. Per ottenere il valore corretto di NLS_LANG utilizzato nella tua istanza di Oracle, esegui

SELECT USERENV ('language') FROM DUAL 
+0

Grazie per la risposta, ho finalmente ricevuto una risposta dai miei DBA.Per la nostra installazione 11gR2, il SET CARATTERE è 'WE8MSWIN1252' e il SET CARATTERE NAZIONALE è 'AL16UTF16'. Sembra che il driver non rilevi correttamente il set di codifica nelle variabili sopra. Il controllo degli attributi 'encoding' e 'nencoding' sulla connessione restituisce 'US-ASCII' in entrambi i casi che non è corretto. Ricevo ancora lo stesso errore DatabaseError quando provo a NLS_LANG su 'AL16UTF16', che dal momento che la mia connessione allo schema è rimossa (e sarà anche in produzione) spiega perché non è possibile accedere a questi file. – snarkyname77

+0

Nella mia situazione, il mio risultato dalla query precedente è "AMERICAN_AMERICA.US7ASCII". Tuttavia, i miei inserti Unicode hanno iniziato a funzionare correttamente una volta che il mio NLS_LANG era impostato su "_.AL32UTF8" (senza virgolette). – davidjb

+0

Il mio risultato dalla query precedente è AMERICAN_AMERICA.WE8MSWIN1252. @davidjb, come lo si imposta a quel valore senza virgolette. Cosa hai importato nel tuo scope per ottenerlo? – ThatAintWorking

Problemi correlati