>  기사  >  백엔드 개발  >  Cx_Oracle 쿼리 시 UnicodeDecodeError 문제를 Python으로 해결합니다.

Cx_Oracle 쿼리 시 UnicodeDecodeError 문제를 Python으로 해결합니다.

高洛峰
高洛峰원래의
2017-02-16 11:13:591642검색

최근 프로젝트에서 100만 개 이상의 레코드가 포함된 테이블을 쿼리한 후 일부 데이터 통계를 수행해야 했는데 이 과정에서 일부 데이터만 쿼리한 후에 UnicodeDecodeError가 발생하는 것을 발견했습니다.
여기에서는 쿼리를 위해 sqlalchemy 라이브러리를 사용하고 내부적으로 Cx_Oracle을 사용하여 해당 작업을 수행합니다. 사용된 Python 버전은 3.5.0이고 호스트 시스템은 Windows 2008 Server이며 다음과 유사한 작업이 수행됩니다.

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'])

여기에서는 먼저 데이터베이스에 대한 연결을 만든 다음 해당 쿼리 작업을 수행합니다. 안타깝게도 10개 미만의 레코드를 쿼리한 후 UnicodeDecodeError가 발생했습니다.
원래는 데이터베이스의 서버 인코딩 문제인 줄 알고 create_engine 함수에 인코딩 매개변수를 추가하고 다음과 같이 변경했습니다.

engine = create_engine('oracle://demo:123456@192.168.1.202/TEST',encoding="UTF-8")

또 다른 방법으로는 연결에서 인코딩을 직접 지정하는 방법이 있습니다. 경로는 다음과 유사합니다:

engine = create_engine('oracle://demo:123456@192.168.1.202/TEST?charset=utf-8')

그러나 문제는 아직 해결되지 않았습니다. 인터넷을 검색했지만 적합한 솔루션을 찾을 수 없었습니다. Mysql 데이터베이스를 사용할 때(저는 개인적으로 Postgresql을 더 좋아합니다), 잘못된 문자가 나타날 때 다음 작업을 자주 수행했다는 것이 기억났습니다.

set names gbk;

우리는 설정했습니다. 터미널에서 문자 깨짐 문제를 해결하기 위해 서버 인코딩이 아닌 클라이언트 인코딩을 이런 방식으로 사용합니다(Postgresql의 기본 데이터베이스는 UTF-8이므로 문자 깨짐 가능성이 낮습니다). 또한 Linux에서 Oracle 클라이언트를 설치하는 경우 NLS_LANG라는 환경 변수가 설정됩니다. 자세한 내용은 Ubuntu 14.04에 Oracle Instant Client 설치 문서를 참조하세요. 물론 이 문서에서는 일부 세부 사항을 소개하지 않습니다.
일반적으로 cmd에서 다음과 같이 설정합니다.

setenv NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

Oracle 메시지에 사용되는 언어는 중국어 간체이고 클라이언트의 문자 집합은 GBK로 지정합니다.
또한 다음 명령문을 실행하여 위 작업이 올바른지 확인할 수도 있습니다.

SELECT * FROM v$nls_parameters;

위 데이터베이스 서버가 Windows에 배포되었으므로 결과는 당연히 GBK이므로 고객이 만약 클라이언트는 디코딩을 위해 UTF8 문자 세트를 사용하므로 디코딩 오류는 자연스럽게 발생합니다.
주의해야 할 점은 데이터베이스 서버와 클라이언트의 인코딩이 일관되어야만 비ASCII 인코딩을 정상적으로 표시할 수 있으며, sqlalchemy에서는 기본적으로 쿼리 문자열을 강제로 유니코드로 변환한다는 점입니다. 따라서 Python3에서는

>>> a='中国'.encode('gbk')
>>> a
b'\xd6\xd0\xb9\xfa'

의 과정과 유사합니다. sqlalchemy에서는 강제 인코딩 변환으로 인해

>>> 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

의 과정과 유사하게 됩니다. 따라서 위와 같은 문제가 발생합니다. . 일반적인 상황에서는 인코딩을 GBK:

>>> a.decode('gbk')
'中国'

로 지정해야 하며 NLS_LANG 설정은 위 인코딩을 GBK로 수정하는 것과 같습니다.

Python에 대한 자세한 내용 - Cx_Oracle 쿼리 시 UnicodeDecodeError 문제 해결에 대한 내용은 PHP 중국어 웹사이트에서 관련 기사를 참고하세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.