Unicode_literals и type()
У меня возникают проблемы с поддержкой python2 и python3 при вызове type()
. Это демонстрирует проблему:
from __future__ import unicode_literals
name='FooClass'
type(name, (dict,), {})
Нет проблем на python3, но на python2:
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(name, (dict,), {})
TypeError: type() argument 1 must be string, not unicode
Это связано с Любые ошибки с использованием unicode_literals в Python 2.6?. В этом вопросе кто-то рекомендует typecasting для байта, так что наивно я думал об использовании six.b()
:
A "поддельный" байтовый литерал. данные всегда должны быть нормальным строковым литералом. В Python 2, b() возвращает 8-битную строку. В Python 3 данные кодируются с кодировкой latin-1 в байтах.
Итак, это выглядит так:
from __future__ import unicode_literals
import six
name='FooClass'
type(six.b(name), (dict,), {})
Но он не работает как на python2, так и на python3:
$ python2 test.py
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be string, not unicode
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 6, in <module>
type(six.b(name), (dict,), {})
TypeError: type() argument 1 must be str, not bytes
Итак, кажется, что действительно, type()
хочет, чтобы python2 str была python3 bytestring на python2, но ему нужна строка python3, которая представляет собой строку юникода python2 на python3.
Как вы думаете?
Я что-то не понимаю?
Или существует ли реальная несовместимость с type()
на python 2 и 3?
Нет ли способа иметь один и тот же вызов type()
, поддерживающий как 2, так и 3?
Не должен ли инструмент, подобный six
, обернуть вокруг type()
в этом случае?
Ответы
Ответ 1
six.b
записывается в предположении, что вы не будете использовать unicode_literals
(и что вы передадите ему строковый литерал, как указано в документации), поэтому реализация Python 2 просто def b(s): return s
как строковый литерал Python 2 уже является байтовой строкой.
Либо не используйте unicode_literals
в этом модуле, либо используйте (как следует из комментариев) str(name)
. В Python 3 это не-op. В Python 2 он бесшумно преобразует строку юникода в байтовую строку (предполагая некоторую кодировку, которую я не могу запомнить, но это надмножество ASCII, поэтому все должно быть хорошо).