你的python内部是用什么编码表示unicode的?

comp.lang.python上看到关于unicode转换的一个线索,Christos TZOTZIOY Georgiou给出了判断python内部表示unicode的编码的方式--使用sys.maxunicode。

如果sys.maxunicode的返回值是65535,说明python是用--enable-unicode=ucs2编译的,如果返回值是1114111,说明是用--enable-unicode=ucs4编译的。

在我的gentoo上实验结果如下:

In [1]: import sys
In [2]: sys.maxunicode
Out[2]:
1114111

呵呵,是使用UCS-4表示unicode的,就算是很生僻很生僻的字也能处理哦

由于好奇,又看了看/usr/portage/dev-lang/python/python-2.3.4-r1.ebuild,想看看gentoo是如何判断采用什么参数编译python的。

相关的代码如下:
    # super-secret switch. don't use this unless you know what you're
    # doing. enabling UCS2 support will break your existing python
    # modules
    use ucs2 \
        && myconf="${myconf} --enable-unicode=ucs2" \
        || myconf="${myconf} --enable-unicode=ucs4"

是使用ucs2这个use flag来定义--enable-unicode的。当激活ucs2,就采用--enable-unicode=ucs2,当ucs2被disable时,就采用--enable-unicode=ucs4。

那么如果是手工编译python,不给出--enable-unicode的话,python又会如何处理呢?看看Python的安装代码吧。
$ tar jxf /usr/portage/distfiles/Python-2.3.4.tar.bz2
$ cd Python-2.3.4
$ ./configure --help | grep unicode -u1
  --disable-ipv6           Disable ipv6 support
  --enable-unicode[=ucs[24]]
                           Enable Unicode strings (default is yes)

默认的--enable-unicode的参数是yes。那么到底是ucs2还是ucs4呢?检查configure的源码吧
echo "$as_me:$LINENO: checking what type to use for unicode" >&5
echo $ECHO_N "checking what type to use for unicode... $ECHO_C" >&6
# Check whether --enable-unicode or --disable-unicode was given.
if test "${enable_unicode+set}" = set; then
  enableval="$enable_unicode"

else
  enable_unicode=yes
fi;

if test $enable_unicode = yes
then
  # Without any arguments, Py_UNICODE defaults to two-byte mode
  case "$have_ucs4_tcl" in
  yes) enable_unicode="ucs4"
       ;;
  *)   enable_unicode="ucs2"
       ;;
  esac
fi



case "$enable_unicode" in
ucs2) unicode_size="2"
      cat >>confdefs.h <<\_ACEOF
#define Py_UNICODE_SIZE 2
_ACEOF

      ;;
ucs4) unicode_size="4"
      cat >>confdefs.h <<\_ACEOF
#define Py_UNICODE_SIZE 4
_ACEOF

      ;;
esac


可以看出,当--enable-unicode=yes时,configure是根据$have_ucs4_tcl的值来决定是使用UCS-2还是UCS-4,并体现在Py_UNICODE_SIZE宏中。
echo "$as_me:$LINENO: checking for UCS-4 tcl" >&5
echo $ECHO_N "checking for UCS-4 tcl... $ECHO_C" >&6
have_ucs4_tcl=no
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
/* confdefs.h.  */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h.  */

#include <tcl.h>
#if TCL_UTF_MAX != 6
# error "NOT UCS4_TCL"
#endif
int
main ()
{

  ;
  return 0;
}
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
  (eval $ac_compile) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); } &&
         { ac_try='test -s conftest.$ac_objext'
  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
  (eval $ac_try) 2>&5
  ac_status=$?
  echo "$as_me:$LINENO: \$? = $ac_status" >&5
  (exit $ac_status); }; }; then


cat >>confdefs.h <<\_ACEOF
#define HAVE_UCS4_TCL 1
_ACEOF

  have_ucs4_tcl=yes

else
  echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5

fi
rm -f conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $have_ucs4_tcl" >&5
echo "${ECHO_T}$have_ucs4_tcl" >&6

原来是根据tcl.h中TCL_UTF_MAX宏是否为6来判断的,如果为6,则使用UCS-4,如果不为6(包括未定义),则使用UCS-2。
Tags: gentoo, linux, python