我对显示“英联”的民族字符有问题王国.US7ASCII“使用Python 3.3 cx_Oracle 5.1.2和”NLS_LANG“环境变量的Oracle 11数据库。 Db表列类型为“VARCHAR2(2000字节)”
如何在Python中显示来自Oracle US7ASCII的字符串“£aÀÃÄÆÈ”?这将是某种黑客攻击。 hank可以在所有其他脚本语言Perl、PHP、PL/SQL和python2.7中工作,但在python3.3中却不能工作。在
在oracle11数据库中,我创建了安全性_提示。回答=“一个··············。应答列类型为“VARCHAR2(2000字节)”。在
现在,当使用cxu Oracle和默认NLS LANG时,我得到“a”
当使用NLS_LANG=“ENGLISH_UNITED”时王国.US7ASCII“我明白了
"UnicodeDecodeError: 'ascii' codec can't decode byte 0xa3 in position 0: ordinal not in range(128)"
更新1 我取得了一些进展。当切换到Python2.7和用于Python2.7的cx峎oracle5.1.2时,问题就消失了(我从数据库中获得了全部>;127个字符)。在Python中,2个字符串表示为字节,而在python3中+字符串表示为unicode。我仍然需要Python3.3的最佳解决方案。在
更新2 这个问题的一个可能的解决方案是使用rawtohex(utl_生的。铸成的参见下面的代码。在
^{pr2}$我的脚本的源代码在GitHub和GitHub 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 Oracle和 Importing from Oracle using the correct encoding with Python
我认为你不应该再耍这种恶作剧了。NLS_LANG只需设置为客户端的默认编码。看看更可靠的选择:
哪个选项最好取决于非ASCII字符的常见程度。如果有更多相同问题的表,我建议选择1。如果这是唯一的表,选项2。如果整个表中只有几个非ASCII字符,并且它们的丢失不是什么大问题:选项3。在
如果一个新的或未定义的数据被强行插入数据库,那么当你不能正确地将一个新的或未定义的数据插入数据库中时,你会发现新的或未定义的数据插入数据库。在
编辑:请参阅Oracle对NLS_LANG faq中类似设置示例的评论(我的重点是):
如果您想在客户机应用程序中获得未更改的ASCII字符串,最好的方法是以二进制模式从DB传输它。所以,第一次转换必须在服务器端借助^{} 包和标准^{} 函数关闭。在
您在
cursor.execute
中选择的内容可能如下所示:在客户机上,您得到了一个十六进制字符的字符串,它可以在^{} 函数的帮助下转换为字符串表示:
^{pr2}$另外,我不懂
Python
语言,所以最后的语句可能不正确。在相关问题 更多 >
编程相关推荐