การแปลงสตริง 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'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
คุณแน่ใจหรือว่า valuee ไม่ใช่สตริง Unicode อยู่แล้ว? เพราะมันเป็นค่าเริ่มต้นใน python3 แต่ปัญหาแรกคือ data ไม่ใช่สิ่งที่คุณคิด... ทำดีๆ import pprint pprint.pprint(data)   -  person Maresh    schedule 20.08.2015
comment
@Maresh ไม่ ไม่ พวกเขาอยู่ในยูนิโค้ด แต่เมื่อฉันทำ pprint พวกเขามีการเพิ่มพิเศษเข้าไป นั่นคือสิ่งที่ฉันพยายามทำ กำจัดคุณออกไป   -  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 เขาพูดถึงข้อมูลที่ถูกเลือกจาก Python3 นั่นคือเหตุผลที่ฉันถาม @Celeritas pprint เป็นเพียงการแสดงให้เราเห็นว่า data คืออะไรกันแน่ เพราะจากข้อผิดพลาดที่คุณรายงาน ดูเหมือนว่ามันจะเป็น dicts ที่ซ้อนกันจริงๆ   -  person Maresh    schedule 20.08.2015
comment
@Celeritas เราต้องการเห็นผลลัพธ์ของ pprint หรือ print หรือ type :) ดูความคิดเห็นก่อนหน้าของฉัน   -  person Maresh    schedule 20.08.2015
comment
ที่ไหน u''s ปรากฏที่ไหน? แน่นอนว่าจะปรากฏใน repr(u'äöü') แต่ print(u'äöü') ควรถอดรหัสยูนิโค้ดอย่างถูกต้องไปยังเทอร์มินัลการเข้ารหัสที่เหมาะสม   -  person dhke    schedule 20.08.2015
comment
@Maresh - อย่างแน่นอน มันถูกดองใน Python 3 ดังนั้น OP จึงมั่นใจได้ว่าเป็นสตริง Unicode อย่างไรก็ตาม สตริง Unicode ใน Python 2 มีคำนำหน้า u ดังนั้น OP จึงต้องการทำให้สตริง ไม่ใช่ Unicode   -  person TigerhawkT3    schedule 20.08.2015
comment
ใช่. ฉันคิดว่าเขาต้องการจากไบต์เป็น str แย่จัง @Celeritas ได้ผลลัพธ์เต็มแล้ว pprint(data)? จากข้อความแสดงข้อผิดพลาดของคุณ data ดูเหมือนว่า: { 'one': {...} } ดังนั้นคุณกำลังพยายามเรียก .encode ด้วย dict ไม่ใช่สตริง นั่นคือสิ่งที่เราต้องการตรวจสอบ   -  person Maresh    schedule 20.08.2015
comment
@Maresh ตกลงเพิ่มเอาต์พุตแบบเต็ม ฉันไม่ได้พยายามทำอะไรที่ซับซ้อนจริงๆ แค่ใช้ตัวแปรในพจนานุกรม BTW ฉันคิดว่าคุณพูดถูกเกี่ยวกับสิ่งที่ซ้อนกัน แล้วฉันจะวนซ้ำพจนานุกรมที่ซ้อนกันและแปลงทุกอย่างเป็น ASCII ได้อย่างไร ฉันจำเป็นต้องแปลงทุกอย่างเป็น ASCII หรือไม่? ฉันแค่ต้องการใช้ค่าเพื่อเชื่อมต่อกับฐานข้อมูล   -  person Celeritas    schedule 20.08.2015
comment
ขอบคุณ. นั่นคือสิ่งที่ฉันคิดว่า คุณมี dicts ซ้อนกัน :) คุณต้องทำสิ่งนั้นซ้ำ ๆ และทดสอบว่าค่าประเภทใด ตรวจสอบคำตอบของฉัน   -  person Maresh    schedule 20.08.2015
comment
@Celeritas ดังนั้นคำตอบใด ๆ ด้านล่างนี้ช่วยคุณได้หรือไม่? หากปัญหาของคุณได้รับการแก้ไขแล้ว โปรดทำเครื่องหมายด้วย :)   -  person Maresh    schedule 21.08.2015
comment
@Maresh ไม่ไม่เต็มที่ มีคำสั่งที่ฉันไม่เข้าใจมากเกินไป เช่น isinstance และ self   -  person Celeritas    schedule 22.08.2015
comment
Isinstance เพียงตรวจสอบว่าค่าเป็น 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 ก็อาจจะไม่ตรงกัน แต่คุณจะต้องเข้ารหัสข้อความยูนิโค้ดด้วยวิธีใดวิธีหนึ่ง - person Roland Smith; 21.08.2015

คุณมี dicts ที่ซ้อนกัน ดังนั้นคุณต้องมีสิ่งนี้ (ทำเร็วมากเพียงเพื่อให้คุณมีความคิด):

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' codec can't encode character หากคุณไม่ได้ระบุคุณ ต้องการละเว้นที่ไม่ใช่ 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