2016-09-19 7 views
1

Мне нужно перенести некоторый код из Python2 в Python3, а основная проблема, похоже, в байтах, потому что str (bytes) дает мне b'%s' результат, но '%s' необходим, поэтому я решил override __str__() метод класса байтов для печати именно того, что я хочу.Переопределить встроенный метод __str__ в python

Я попытался исправить builtins.bytes с классом, унаследованным от байтов, но, похоже, работает только для одного файла, а не для всего проекта, а также не влияет на литералы байтов (b'').

Если есть какие-либо другие способы (менее болезненные) для порта от py2 до py3, было бы неплохо их увидеть.

Использование .decode('UTF-8') неприемлемо, так как проект более 4k строк и добавление метода декодирования ко всем необходимым местам приведет к подсчету прогрессивных ошибок, а также некоторые из этих .decode мест находятся в 3-х партийных библиотеках.

Я пытался сделать что-то вроде этого:

import builtins 

class StrBytes(builtins.bytes): 
    def __str__(self): 
     return self.decode('UTF-8') 

builtins.bytes = StrBytes 

Тогда, если я использую bytes() он создает StrBytes объект и str(bytes()) именно то, что я хочу. Таким образом, это плохо, потому что она не распространяется на построение байтов объекта из байтов литералов:

>>> type(bytes()) 
    <class 'StrBytes'> 

>>> type(b'') 
    <class 'bytes'> 

И я не уверен, если это работает для всего проекта, а не только один файл.

Во многих различных местах моего кода, у меня есть что-то вроде этого:

return b''.join(some_extra_values) 

keys = [b'1', b'2', b'3'] # actually keys are given from another part of code 
for key in keys: 
    some_dict[key] = some_value 

some_dict['1'] # works in py2, not in py3, KeyError 
+0

Не могли бы вы опубликовать исполняемый, самодостаточный пример? – dm03514

+0

Не могли бы вы [изменить свой вопрос] (https://stackoverflow.com/posts/39574286/edit) включить пример строки кода, которую нужно преобразовать, и того, что вы пробовали, кроме 'decode() '? – cxw

ответ

2

Правило с текстом является «расшифровывает на вход, кодирование на выходе.» Несмотря на то, что была проделана большая работа по упрощению написания кода, совместимого между v2 и v3, всегда будут некоторые несоответствия, и тот факт, что Python 3 больше не определяет символ unicode, является одним из них.

Неплохо пробовать и исправлять встроенные типы в Python. Поскольку они определены в C, нет эффективного способа исправления их методов.

Один возможно полезный инструмент

from __future__ import unicode_literals 

, когда при вставке в начале программы будет интерпретировать все строковые литералы как строки Unicode, а не байтовых строк.

Другой способ адаптации вашего кода - использовать тот факт, что Python 3 не реализует имя для обнаружения функций накопителя. Таким образом, вы могли бы написать, например

try: 
    unicode = unicode # RHS raises NameError on Python 3 
except NameError: 
    unicode = str 

Затем вы можете проверить типы текстов, написав

if type(s) is unicode: 
    ... 

и сравнение должно работать в обоих v2 и v3.

Вам не нужно вставлять много вызовов для декодирования, если вы правильно декодируете на входе, и их нужно кодировать только тогда, когда строка должна быть передана внешнему инструменту какого-либо типа.

+0

Я уже использую unicode_literals, но проблема существует в Py3 с префиксом b '' для всех строк, потому что некоторые из сторонних библиотек используют b ''. Join (...) способ построить свой вывод. Поэтому я подумал, что было бы проще исправлять встроенные функции, а не исправлять весь код. – Sindbag

Смежные вопросы