gpt4 book ai didi

python - 如何使用 Python cx_Oracle 从 US7ASCII Oracle 中读取国家字符(>127)?

转载 作者:太空宇宙 更新时间:2023-11-04 01:20:58 25 4
gpt4 key购买 nike

我在使用 Python 3.3 cx_Oracle 5.1.2 和“NLS_LANG”环境变量显示来自“ENGLISH_UNITED KINGDOM.US7ASCII”Oracle 11 数据库的国家字符时遇到问题。db 表列类型为“VARCHAR2(2000 BYTE)”

如何在 Python 中显示来自 Oracle US7ASCII 的字符串“£aÀÁÂÃÄÅÆÇÈ”?这将是某种黑客攻击。hank 适用于所有其他脚本语言 Perl、PHP、PL/SQL 和 Python 2.7,但不适用于 Python 3.3。

在 Oracle 11 数据库中,我创建了 SECURITY_HINTS.ANSWER="£aÀÁÂÃÄÅÆÇÈ"。 ANSWER 列类型是“VARCHAR2(2000 BYTE)”。

现在,当使用 cx_Oracle 和默认的 NLS_LANG 时,我得到“¿a¿

当使用 NLS_LANG="ENGLISH_UNITED KINGDOM.US7ASCII"我得到

"UnicodeDecodeError: 'ascii' codec can't decode byte 0xa3 in position 0: ordinal not in range(128)"

更新1我取得了一些进步。当切换到 Python 2.7 和 Python 2.7 的 cx_Oracle 5.1.2 时,问题就消失了(我从 db 得到了所有 >127 个字符)。在 Python 2 中,字符串表示为字节,在 Python 3+ 中,字符串表示为 unicode。我仍然需要 Python 3.3 的最佳解决方案。

更新2该问题的一种可能解决方案是使用 rawtohex(utl_raw.cast_to_raw 参见下面的代码。

cursor.execute("select rawtohex(utl_raw.cast_to_raw(ANSWER)) from security_hints where userid = '...'")
for rawValue in cursor:
print (''.join(['%c' % iterating_var for iterating_var in binascii.unhexlify(rawValue[0])]))

我脚本的源代码在下面或在 GitHubGitHub Sollution

def test_nls(nls_lang=None):
print (">>> run test_nls for %s" %(nls_lang))
if nls_lang:
os.environ["NLS_LANG"] = nls_lang
os.environ["ORA_NCHAR_LITERAL_REPLACE"] = "TRUE"

connection = get_connection()
cursor = connection.cursor()
print("version=%s\nencoding=%s\tnencoding=%s\tmaxBytesPerCharacter=%s" %(connection.version, connection.encoding,
connection.nencoding, connection.maxBytesPerCharacter))

cursor.execute("SELECT USERENV ('language') FROM DUAL")
for result in cursor:
print("%s" %(result))

cursor.execute("select ANSWER from SECURITY_HINTS where USERID = '...'")
for rawValue in cursor:
print("query returned [%s]" % (rawValue))
answer = rawValue[0]
str = ""
for iterating_var in answer:
str = ("%s [%d]" % (str, ord(iterating_var)))

print ("str %s" %(str))

cursor.close()
connection.close()

if __name__ == '__main__':
test_nls()
test_nls(".AL32UTF8")
test_nls("ENGLISH_UNITED KINGDOM.US7ASCII")

查看下面的日志输出。

run test_nls for None
version=11.1.0.7.0
encoding=WINDOWS-1252 nencoding=WINDOWS-1252 maxBytesPerCharacter=1
ENGLISH_UNITED KINGDOM.US7ASCII
query returned [¿a¿¿¿¿¿¿¿¿¿]
str [191] [97] [191] [191] [191] [191] [191] [191] [191] [191] [191


run test_nls for .AL32UTF8
version=11.1.0.7.0
encoding=UTF-8 nencoding=UTF-8 maxBytesPerCharacter=4
AMERICAN_AMERICA.US7ASCII
query returned [�a���������]
str [65533] [97] [65533] [65533] [65533] [65533] [65533] [65533] [65533] [65533] [65533]

run test_nls for ENGLISH_UNITED KINGDOM.US7ASCII
version=11.1.0.7.0
encoding=US-ASCII nencoding=US-ASCII maxBytesPerCharacter=1
ENGLISH_UNITED KINGDOM.US7ASCII
Traceback (most recent call last):
File "C:/dev/tmp/Python_US7ASCII_cx_Oracle/showUS7ASCII.py", line 71, in <module>
test_nls("ENGLISH_UNITED KINGDOM.US7ASCII")
File "C:/dev/tmp/Python_US7ASCII_cx_Oracle/showUS7ASCII.py", line 55, in test_nls
for rawValue in cursor:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa3 in position 0: ordinal not in range(128)

我试图在 Django 网页中显示它。但是每个字符都是带有代码 191 或 65533 的字符。

我看过 choosing NLS_LANG for OracleImporting from Oracle using the correct encoding with Python

Cannot Insert Unicode Using cx-Oracle

最佳答案

如果你想在客户端应用程序中得到不变的ASCII 字符串,最好的方法是从数据库中以二进制方式传输它。因此,第一次转换必须借助 UTL_RAW 在服务器端关闭封装与标准rawtohex功能。

您在 cursor.execute 中的选择可能如下所示:

select rawtohex(utl_raw.cast_to_raw(ANSWER)) from SECURITY_HINTS where USERID = '...'

在客户端上,您得到了一串十六进制字符,可以借助 binascii.unhexlify 将其转换为字符串表示形式。功能:

for rawValue in cursor:
print("query returned [%s]" % (binascii.unhexlify(rawValue)))

附言我不懂 Python 语言,所以最后的陈述可能不正确。

关于python - 如何使用 Python cx_Oracle 从 US7ASCII Oracle 中读取国家字符(>127)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21336211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com