최근 프로젝트에서 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 중국어 웹사이트에서 관련 기사를 참고하세요!