Преобразование строк Unicode в строки Ascii в dict

Я прочитал ответ на этот вопрос и все еще получаю сообщение об ошибке AttributeError: 'dict' object has no attribute 'encode' .

я пытался

dic = pickle.load(fileObject)
for v in dic:
    v.encode('ascii', 'ignore')

а также

dic = pickle.load(fileObject)
for key, val in dic.iteritems():
    val.encode('ascii', 'ignore')

и все еще получаю ту же ошибку. При печати переменных все они отображаются с u впереди. Словарь был замаринован под python 3 и распаковывается в python 2.

Я попробовал pp.pprint((dataFromPrevMod).encode('ascii', 'ignore')), и это не сработало.

Если я pprint из словаря, он показывает его содержимое, но в Python 3 каждая строка начинается с u, например u'website': u'exmample.org'

Словарь довольно напечатан в Python 3

{
        'output': {
                'table': 'intersection',
                'file_location': '\\\\storage1\\tpn\\tpn_team\\dev\\asmithe\\',
                'schema': 'asmithe',
                'temporary_location': '\\\\storage1\\tpn\\tpn_team\\dev\\asmithe\
\'
        },
        'tpn_inventory_db_r': {
                'generic_pwd': '51f3tlNE26',
                'db_name': 'tpn',
                'user': 'asmithe',
                'schema': 'asmithe',
                'host': 'example.tpns.org'
        },
        'proj_year': '2005',
        'proj_rules_r': 'C:\\asmithe\\rules.txt',
        'incidents_db_r': {
                'schema': 'tpn_pp_dist',
                'generic_pwd': '51f3tlNE26',
                'db_name': 'tpn',
                'user': 'asmithe',
                'fire_table': 'incident',
                'host': 'example.tpns.org'
        },
        'plots_to_project_r': 'C:\\Users\\asmithe\\Plots.txt',
        'tpn_proj_db_r': {
                'generic_pwd': '51f3tlNE26',
                'db_name': 'tpn inventory',
                'user': 'asmithe',
                'schema': 'test',
                'host': 'example.tpns.org'
        }
}

Словарь довольно напечатан в Python 2 (обратите внимание на добавление u)

{   u'incidents_db_r': {   u'db_name': u'tpn',
                                u'fire_table': u'incident',
                                u'generic_pwd': u'51f3tlNE26',
                                u'host': u'example.tpns.org',
                                u'schema': u'tpn_pp_dist',
                                u'user': u'asmithe'},
    u'tpn_inventory_db_r': {   u'db_name': u'tpn',
                                 u'generic_pwd': u'51f3tlNE26',
                                 u'host': u'example.tpns.org',
                                 u'schema': u'asmithe',
                                 u'user': u'asmithe'},
    u'tpn_proj_db_r': {   u'db_name': u'tpn inventory',
                            u'generic_pwd': u'51f3tlNE26',
                            u'host': u'example.tpns.org',
                            u'schema': u'test',
                            u'user': u'asmithe'},
    u'output': {   u'file_location': u'\\\\storage1\\tpn\\tpn_team\\dev\\asmithe\ \',
                   u'schema': u'asmithe',
                   u'table': u'intersection',
                   u'temporary_location': u'\\\\storage1\\tpn\\tpn_team\\dev\\asmithe idek\\'},
    u'plots_to_project_r': u'C:\\Users\\asmithe\\Plots.txt',
    u'proj_rules_r': u'C:\\asmithe\\rules.txt',
    u'proj_year': u'2005'}

person Celeritas    schedule 20.08.2015    source источник
comment
Примечание. Первый цикл for перебирает ключи, v может быть не лучшим именем переменной. Что такое type(key) и type(val)? В настоящее время похоже, что там есть вложенный словарь.   -  person dhke    schedule 20.08.2015
comment
Кроме того, вы можете показать, что print(val) ?   -  person Anand S Kumar    schedule 20.08.2015
comment
Вы уверены, что значения уже не являются строками Unicode? Потому что это значение по умолчанию в python3. Но первая проблема заключается в том, что data не то, что вы думаете... Сделайте хороший import pprint pprint.pprint(data)   -  person Maresh    schedule 20.08.2015
comment
@Maresh нет, нет, они в юникоде, но когда я делаю pprint, к ним добавляются дополнительные буквы u. Вот что я пытаюсь сделать, избавиться от U.   -  person Celeritas    schedule 20.08.2015
comment
Также помните, что строки Python неизменяемы. Вызов чего-то вроде val.encode(whatever) создает и возвращает вам новую строку, оставляя оригинал без изменений. В этом коде вы игнорируете это новое строковое значение, которое, вероятно, вам не нужно.   -  person bgporter    schedule 20.08.2015
comment
@Maresh - как указано в теге, OP использует Python 2.   -  person TigerhawkT3    schedule 20.08.2015
comment
@TigerhawkT3 TigerhawkT3 Он упомянул, что данные были получены из Python3, поэтому я и спрашиваю. @Celeritas, pprint просто показывает нам, что такое data, потому что из сообщения об ошибке, о которой вы сообщаете, похоже, что это на самом деле вложенные словари.   -  person Maresh    schedule 20.08.2015
comment
@Celeritas, мы хотели бы увидеть результат pprint или print или type :) См. мой предыдущий комментарий.   -  person Maresh    schedule 20.08.2015
comment
Где появляются u''? Они, безусловно, появляются в repr(u'äöü'), но print(u'äöü') должен правильно декодировать юникод в правильную кодировку терминалов.   -  person dhke    schedule 20.08.2015
comment
@Мареш - точно. Он обработан в Python 3, поэтому OP действительно может быть уверен, что это строки Unicode. Однако строки Unicode в Python 2 имеют префикс u, поэтому OP хочет сделать их не Unicode.   -  person TigerhawkT3    schedule 20.08.2015
comment
Да. Я понял, что он хотел от bytes до str, мой плохой. Полный вывод @Celeritas, пожалуйста, pprint(data)? Из вашего сообщения об ошибке data звучит так: { 'one': {...} } значит, вы пытаетесь вызвать .encode в словаре, а не в строке, это то, что мы хотим проверить.   -  person Maresh    schedule 20.08.2015
comment
@Maresh, хорошо, добавил полный вывод. Я действительно не пытаюсь делать ничего сложного, просто использую переменные в словаре. Кстати, я думаю, что вы правы насчет вложенности. Итак, как мне перебрать вложенный словарь и преобразовать все в ascii? Нужно ли мне конвертировать все в ascii? Я просто хочу использовать значения для подключения к базе данных.   -  person Celeritas    schedule 20.08.2015
comment
Спасибо. Так вот что я думаю, у вас есть вложенные словари :) Вам нужно сделать это рекурсивно и проверить, каков тип значения. Проверьте мой ответ   -  person Maresh    schedule 20.08.2015
comment
@Celeritas Итак, помог ли вам какой-либо из приведенных ниже ответов? Если проблема решена, отметьте это, пожалуйста :)   -  person Maresh    schedule 21.08.2015
comment
@ Мареш, нет, не полностью. Я не понимаю слишком много команд, таких как isinstance и self   -  person Celeritas    schedule 22.08.2015
comment
Например, просто проверьте, является ли значение dict или строкой unicode, вы можете просто запустить код, который я предоставил, он сделает свое дело, потому что я не думаю, что вам нужны ключи в виде байтов   -  person Maresh    schedule 22.08.2015


Ответы (3)


Причина, по которой pprint показывает строки Юникода как u'bla', заключается в том, что в Python 2 объекты string и unicode являются типами последовательностей, но они не совпадают.

Поэтому логично, что pprint в Python 2 не показывает их как таковые.

person Roland Smith    schedule 20.08.2015
comment
Имеет ли это значение в том смысле, что я просто хочу использовать значения для подключения к базе данных? - person Celeritas; 20.08.2015
comment
@Celeritas - Вы уже пытались подключиться к базе данных с этими значениями? - person TigerhawkT3; 20.08.2015
comment
@Celeritas Это зависит от формата данных в базе данных. Если вы кодируете строку как UTF-8, а база данных использует UTF-16, она, вероятно, не совпадет. Но вам придется каким-то образом кодировать текст Unicode. - person Roland Smith; 21.08.2015

У вас есть вложенные словари, поэтому вам нужно что-то вроде этого (сделано очень быстро, просто чтобы дать вам представление):

def unicode_to_bytes(d):
    for k in d:
        if isinstance(d[k], dict):
            unicode_to_bytes(d[k])
        elif isinstance(d[k], unicode):
            d[k] = d[k].encode('ascii', 'ignore')

test = {
    'a': u'b',
    'b': {
        'c': u'c',
        'd': {'e': u'f'}
    }
}

unicode_to_bytes(test)

print test

Однако это не забота о ключах.

Надеюсь, поможет.

person Maresh    schedule 20.08.2015
comment
Как насчет d[str(k)] = str(d[k]); del d[k]? - person TigerhawkT3; 20.08.2015
comment
Вы получите: RuntimeError: словарь изменил размер во время итерации с del А также: UnicodeEncodeError: кодек 'ascii' не может кодировать символ, если вы не укажете хотите игнорировать не-ascii. - person Maresh; 20.08.2015
comment
Да, я думаю, есть много способов подойти к этому делу, давайте оставим его самому разбираться с остальным :-P - person Maresh; 20.08.2015

Ради полноты: невероятно сложно написать собственный сборщик, который автоматически кодирует объекты Unicode в строки. Ниже приведено только для Python 2:

import pickle
import sys
from StringIO import StringIO

class EncodingUnpickler(pickle.Unpickler):
    def __init__(self, f, encoding=None):
        pickle.Unpickler.__init__(self, f)
        # we don't want to modify the class variable from pickle.Unpickler
        self.dispatch = self.dispatch.copy()
        self.dispatch[pickle.UNICODE] = EncodingUnpickler.load_unicode
        self.dispatch[pickle.BINUNICODE] = EncodingUnpickler.load_binunicode
        self.encoding = encoding or sys.getdefaultencoding()

    def load_binunicode(self):
        pickle.Unpickler.load_binunicode(self)
        self.append(self.stack.pop().encode(self.encoding))

    def load_unicode(self):
        pickle.Unpickler.load_unicode(self)
        self.append(self.stack.pop().encode(self.encoding))


d = { u'1': u'a', u'2': u'b' }
s = pickle.dumps(d)
unp = EncodingUnpickler(StringIO(s))
du = unp.load()
print du
person dhke    schedule 20.08.2015