【问题标题】:Stringifying an Inline::Python::Object-encoded Unicode string对 Inline::Python::Object 编码的 Unicode 字符串进行字符串化
【发布时间】:2014-04-16 15:10:46
【问题描述】:

Inline::Python::Object 重载'""'(字符串化):

sub __inline_str__ {
    my ($self) = @_;
    return Inline::Python::py_has_attr($self, '__str__') ? $self->__str__() : $self;
}

__str__() 方法尝试转换为 ASCII,这意味着如果 Inline::Python::Object 对象表示 Python Unicode 字符串,可能的结果是:

exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\xe7' in position 6: ordinal not in range(128) at line 1252

似乎有效的一种解决方法是将$self->__str__() 替换为$self->encode('utf8')。我不太喜欢像这样修改模块,并且子类化它似乎是一个相当大的挑战。此外,我不能 100% 确定为什么我的修复程序会起作用,这有点令人担忧。

我很确定我不是第一个需要在 Perl 中使用 Python Unicode 字符串的人。这应该怎么做?

【问题讨论】:

  • 正常行为是让您的 Python 代码显式编码;不要使用str(unicodevalue),在可以使用unicodevalue.encode('utf8')的地方。
  • 这是有道理的,但不幸的是,“我的”Python 代码并不是真正属于我的,我使用Inline::Python 将 HTTP4Store Python 库加载到 Perl 中。必须修改 Python 库与必须修改 Inline::Python 一样令人恼火,因为我对 Python 并不精通,所以风险更大。 :-(
  • 我承认不知道 Perl 会调用什么 __inline_str__ sub for;如果 Python 源代码被解码为 Unicode,然后被解析,那么这就是出错的地方,因为 Python 中的字节字符串文字包含普通的未编码字节(因此值为 0-255)。你知道 Perl 最初使用什么编解码器来解码源代码吗?
  • 我不认为除了我的 Perl 源代码中包含的内容(即 from HTTP4Store import HTTP4Store as HTTP4Store_Python)之外,Perl 实际上还涉及 Python 源代码。不过老实说,我真的不确定Inline::Python 是如何工作的,而且我在 XS 方面也不够好,无法从源头上分辨出来......
  • 如果在任何 Python 对象上调用此函数,则不能使用 .encode()(它不是为任意对象定义的)。如果字符串表示用于调试,那么您可以调用repr(self)(通过py_call_function)而不是self.__str__()

标签: python perl unicode


【解决方案1】:

似乎有效的一种解决方法是替换 $self->str() 使用 $self->encode('utf8')。

这是处理此问题的正确方法。该代码会将任何 UTF 字符编码为如下所示:

>>> u'\ufdef'.__str__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\ufdef' in position 0: ordinal not in range(128)
>>> u'\ufdef'.encode('utf-8')
'\xef\xb7\xaf'

然后您可能希望在 PERL 中使用 UTF-8 解码器来正确显示该值。

【讨论】:

  • 如果你能证明py_has_attr($self, '__str__') 永远不会为没有encode 方法的对象返回真值,那将是可靠的。但是,即使在那种情况下,它也没有真正回答我关于如何使用 Inline::Python 的问题,而不是如何更改它。
猜你喜欢
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 2020-08-28
  • 2013-10-08
  • 2012-03-23
相关资源
最近更新 更多