Python 3.3:访问字符串内部表示形式?

问题描述 投票:0回答:3

在Python> = 3.3中,为了帮助解决Unicode编码和解码问题,我希望能够从Python代码中检查存储在字符串中的实际内部数据。我该怎么办?

[有一个str.encode()方法,该方法返回字节表示形式,但是通常这是由特定编解码器(由“ encoding”参数选择)翻译的字节序列,而不是存储在str对象。

[有一个“ unicode_internal”编码选项,但已弃用,并且尚不清楚在3.3中是否返回真实的内部数据(组织方式如何?)或对其进行某种转换。

PEP 393描述了Unicode数据的内部结构,从中看来,从Python访问此数据将需要报告字符串类型(1/2/4字节),表示形式(ASCII /紧凑)以及包含以下内容的字节数组:字符串内容(我认为其格式为ASCII,UCS1、2或4)。

我尚未在str类型上找到在Python中提供此访问权限的方法。

还有其他方法吗?也许是使用struct的聪明方法?还是公开这些字符串内部信息的C库?

更新2014-03-13:

感谢所有回答有关为什么不希望访问字符串内部结构的建议的人。对于普通的Python程序,这无疑是有效的建议。

尽管如此,我的问题是:该怎么做?

扩展基本原理:是为了解决编码解码问题,其中一个函数(可能在某些库中)创建并返回一个str,而另一个函数(也许在其他库中)应使用以下方法进行处理:那条路。

我想检查该中间str的确切内容,(即:我想将问题空间切成两半),而无需引入进一步的变量,即让一个或另一个python函数将该数据转换为其他数据形式(例如带有转义序列的ASCII)。

还有其他原因,如果其中一个库实际上对内部数据格式敏感,我想知道确切的内部数据。所说的库很可能是用C编写的,可以访问该数据,并且处理不正确。

[此外,确实应该将str视为可无关内部内部表示的代码点序列对待。但是,如果在字符串处理中实际上存在一个错误,我不想被它误导,如果没有,我希望有没有错误的信心。考虑到字符串库的复杂性,零错误将是一个很大的成就。

所以:我应该如何检查字符串的内部结构?

python string unicode python-3.3
3个回答
0
投票

Python中的Unicode字符串应被视为Unicode代码点的序列。内部表示方式与编码和解码问题完全无关。

您可以通过对字符串的各个字符使用ord()函数来访问Unicode代码点的数值:

>>> list(map(ord, "abc €"))
[97, 98, 99, 32, 8364]

我认为这对于调试编码问题(或其他任何问题)没有特别的帮助,但是它可以澄清Unicode字符串在概念上是什么。


0
投票

仅出于性能原因内部转换为Unicode值introduced by PEP-393以便于节省空间。

因此,它们对在Python代码中对Unicode str值的编码和解码如何产生零影响。从Python访问内部表示绝对是no point。字符A可以存储为41410041000000,具体取决于字符串中最高代码点所需的空间,但仍会以ASCII,拉丁语- 1或UTF-8。

除非您正在编写必须处理此内部表示形式的C扩展,否则完全不必担心Python实际存储数据的方式。

[要调试编码或解码问题,我将使用41仅使用ASCII码点和Python字符串文字转义符来表示字符串,或者您可以使用ascii() function将每个字符的单个字符转换为整数。

对于字节值,ascii()也很方便,可以快速将一系列字节转换为其十六进制表示形式。


0
投票

Python的内部字符串表示形式严格来说是一个内部实现细节,从一个版本的Python到下一个版本以及在操作系统上可能会有所不同。由于问题指定的Python版本号> = 3.3,所以我假设我们正在谈论CPython(1/2/4字节字符表示),并使用id()给出内存地址的CPython实现细节。以下使用Ubuntu 19.10的系统CPython 3.7.5。

ord() function

输出:

ord()

您会在十六进制的末尾看到“ ABCDE”,从41到45递增。如果从Unicode代码点范围128-255向该字符串添加了字符,例如0xA2处的分号,则“¢ABCDE ”,该字符仍然可以用一个字节表示,因此CPython就是这样做的,尽管由于某些原因,字符串前面的空行增加了:

binascii.hexlify() function

如果将大于Unicode 255的字符添加到字符串中,例如0x153处的oe-ligature“ –ABCDE”,则整个字符串将转换为每个字符两个字节,其中“ –”是小尾数“ 5301 “,” A“为” 4100“,依此类推:

binascii.hexlify()
© www.soinside.com 2019 - 2024. All rights reserved.