Dans un projet récent, j'ai dû interroger une table contenant plus d'un million d'enregistrements, puis effectuer des statistiques de données. Cependant, au cours de ce processus, j'ai découvert qu'une erreur UnicodeDecodeError se produisait après l'interrogation de quelques éléments de données seulement.
Ici, nous utilisons la bibliothèque sqlalchemy pour les requêtes, et Cx_Oracle est utilisé en interne pour effectuer les opérations correspondantes. La version Python utilisée est 3.5.0, le système hôte est Windows 2008 Server, puis des opérations similaires aux suivantes sont effectuées :
from sqlalchemy import create_engine engine = create_engine('oracle://demo:123456@192.168.1.202/TEST') conn = engine.connect() sql = 'select t.type from TS t' result = conn.execute(sql) for row in result: print(row['type'])
Ici, nous créons d'abord une connexion à la base de données, puis effectuons l'opération de requête correspondante. Malheureusement, une erreur UnicodeDecodeError s'est produite après avoir interrogé moins de 10 enregistrements.
À l'origine, je pensais qu'il s'agissait d'un problème d'encodage du serveur dans la base de données, j'ai donc ajouté le paramètre encoding à la fonction create_engine et je l'ai modifié en :
engine = create_engine('oracle://demo:123456@192.168.1.202/TEST',encoding="UTF-8")
L'autre méthode disponible consiste à spécifier directement l'encodage dans le chemin de connexion. , semblable à ce qui suit :
engine = create_engine('oracle://demo:123456@192.168.1.202/TEST?charset=utf-8')
Mais le problème n'est toujours pas résolu. J'ai cherché sur Internet mais je n'ai pas trouvé de solution appropriée. Je me suis soudainement rappelé que lorsque j'utilisais la base de données Mysql (j'aime personnellement davantage Postgresql), lorsque des caractères tronqués apparaissaient, nous effectuions souvent les opérations suivantes :
set names gbk;
Nous définissons le codage côté client de cette manière au lieu du codage côté serveur pour résoudre le problème des caractères tronqués sur le terminal (puisque la base de données par défaut de Postgresql est UTF-8, la possibilité de caractères tronqués est faible). De plus, lors de l'installation du client Oracle sous Linux, une variable d'environnement de NLS_LANG
est définie. Pour plus de détails, veuillez vous référer à l'article Installer Oracle Instant Client dans Ubuntu 14.04. Bien entendu, cet article n'introduit pas certains détails.
Généralement, nous effectuons les réglages suivants dans cmd :
setenv NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
Nous précisons que la langue utilisée par les messages Oracle est le chinois simplifié et que le jeu de caractères du client est GBK.
De plus, nous pouvons également exécuter l'instruction suivante pour nous assurer que l'opération ci-dessus est correcte :
SELECT * FROM v$nls_parameters;
Puisque le serveur de base de données ci-dessus est déployé sous Windows, le résultat est naturellement GBK, donc si notre Le client utilise le jeu de caractères UTF8 pour le décodage, donc des erreurs de décodage se produiront naturellement.
Ce que nous devons noter, c'est que ce n'est que lorsque l'encodage du serveur de base de données et du client est cohérent que nous pouvons afficher normalement l'encodage non-ASCII, et sqlalchemy forcera la conversion de la chaîne de requête en Unicode par défaut. Par conséquent, il est similaire au processus suivant en Python3 :
>>> a='中国'.encode('gbk') >>> a b'\xd6\xd0\xb9\xfa'
Dans sqlalchemy, en raison de la conversion forcée du codage, il est similaire au processus suivant :
>>> a.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd6 in position 0: invalid continuation byte
Par conséquent, le le problème ci-dessus se produit. Dans des circonstances normales, l'encodage doit être spécifié comme GBK :
>>> a.decode('gbk') '中国'
et le paramètre NLS_LANG
équivaut à modifier l'encodage ci-dessus en GBK.
Pour en savoir plus sur Python et résoudre le problème d'UnicodeDecodeError lors de l'interrogation de Cx_Oracle, veuillez faire attention au site Web PHP chinois pour les articles connexes !