在 Python 2 和 3 中获得相同的 Unicode 字符串长度?

sda*_*aau 4 python python-2.7 python-3.x

呃,Python 2 / 3 太令人沮丧了......考虑这个例子test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
if sys.version_info[0] < 3:
  text_type = unicode
  binary_type = str
  def b(x):
    return x
  def u(x):
    return unicode(x, "utf-8")
else:
  text_type = str
  binary_type = bytes
  import codecs
  def b(x):
    return codecs.latin_1_encode(x)[0]
  def u(x):
    return x

tstr = " ? "

sys.stderr.write(tstr)
sys.stderr.write("\n")
sys.stderr.write(str(len(tstr)))
sys.stderr.write("\n")
Run Code Online (Sandbox Code Playgroud)

运行它:

$ python2.7 test.py 
 ? 
5
$ python3.2 test.py 
 ? 
3
Run Code Online (Sandbox Code Playgroud)

太好了,我得到了两种不同尺寸的字符串。希望将绳子包裹在我在网上找到的这些包装纸之一中会有帮助吗?

为了tstr = text_type(" ? ")

$ python2.7 test.py 
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    tstr = text_type(" ? ")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal not in range(128)
$ python3.2 test.py 
 ? 
3
Run Code Online (Sandbox Code Playgroud)

为了tstr = u(" ? ")

$ python2.7 test.py 
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    tstr = u(" ? ")
  File "test.py", line 11, in u
    return unicode(x)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal not in range(128)
$ python3.2 test.py 
 ? 
3
Run Code Online (Sandbox Code Playgroud)

为了tstr = b(" ? ")

$ python2.7 test.py 
 ? 
5
$ python3.2 test.py 
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    tstr = b(" ? ")
  File "test.py", line 17, in b
    return codecs.latin_1_encode(x)[0]
UnicodeEncodeError: 'latin-1' codec can't encode character '\u25b2' in position 1: ordinal not in range(256)
Run Code Online (Sandbox Code Playgroud)

为了tstr = binary_type(" ? ")

$ python2.7 test.py 
 ? 
5
$ python3.2 test.py 
Traceback (most recent call last):
  File "test.py", line 21, in <module>
    tstr = binary_type(" ? ")
TypeError: string argument without an encoding
Run Code Online (Sandbox Code Playgroud)

嗯,这确实让事情变得简单。

那么,如何在 Python 2.7 和 3.2 中获得相同的字符串长度(在本例中为 3)?

sda*_*aau 5

好吧,事实证明Python 2.7 中的unicode()encoding有一个参数,这显然有帮助:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
if sys.version_info[0] < 3:
  text_type = unicode
  binary_type = str
  def b(x):
    return x
  def u(x):
    return unicode(x, "utf-8")
else:
  text_type = str
  binary_type = bytes
  import codecs
  def b(x):
    return codecs.latin_1_encode(x)[0]
  def u(x):
    return x

tstr = u(" ? ")

sys.stderr.write(tstr)
sys.stderr.write("\n")
sys.stderr.write(str(len(tstr)))
sys.stderr.write("\n")
Run Code Online (Sandbox Code Playgroud)

运行这个,我得到了我需要的东西:

$ python2.7 test.py 
 ? 
3
$ python3.2 test.py 
 ? 
3
Run Code Online (Sandbox Code Playgroud)