2016-04-13 1 views
0

Я был бы признателен, если бы кто-то помог мне с этой маленькой проблемой. Я хочу перебрать сложную структуру данных Python (dict, list, tuple, string, bytes, ...) и заменить все байты (байтовые строки) на версию с кодировкой base64. Это необходимо для преобразования исходной сложной структуры данных в JSON (например, json.dumps(complex_data_structure)), поскольку JSON не поддерживает двоичные данные. Мой код уже делает правильные вещи, но есть одна проблема, специфичная для Python. Вот мой код:Получите ссылку на объект Python, итерации по сложному словарю

import sys 
import json 
import base64 


def iter_object(obj): 
    if type(obj) is tuple: 
     iter_tuple(obj) 
    elif type(obj) is dict: 
     iter_dict(obj) 
    elif type(obj) is list: 
     iter_list(obj) 
    else: # non iterable types except of string and bytes etc. 
     if type(obj) is bytes: 
      # THE PROBLEM IS THE COPY OF OBJ! 
      obj = base64.b64encode(obj).decode("ascii") 
     else: 
      pass # we don't care about other data types 


def iter_tuple(obj_tuple): 
    for t in obj_tuple: 
     iter_object(t) 


def iter_list(obj_list): 
    for l in obj_list: 
     iter_object(l) 


def iter_dict(obj_dict): 
    for k, v in obj_dict.items(): 
     iter_object(v) 


def main(): 

    test_dict = { 
     "foo": [1, 3, 4, 5, 6, 7], 
     "bar": 1, 
     "baz": (1, 2), 
     "blub": { 
      "bla": b"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", 
      "ble": { 
       "blu": [ 
        1, 3, b"\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42", 
        (1, [b"\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43"]) 
       ] 
      } 
     } 
    } 

    iter_object(test_dict) 

    print(json.dumps(test_dict)) 

    return 0 


if __name__ == "__main__": 
    sys.exit(main()) 

Проблема заключается линия obj = base64.b64encode(obj).decode("ascii"), потому что он работает на копии не ссылка (сказать в C++). Вот мой вопрос: Есть ли способ обхода этого кода?

спасибо!

ответ

1

Работы над копией ?? Нет. Что происходит, так это то, что функция возвращает значение вместо того, чтобы менять его на месте. Это связано с тем, что строки байтов неизменяемы. В python отсутствует понятие пропуска по значению или ссылке. Переменные не являются ячейками, в которых хранятся объекты, а скорее являются именами какого-либо объекта. И объект может быть

  1. Mutable - list, set, dict
  2. Неизменного - tuple, str, bytes

Таким образом, если функция действует на неизменяемом объекте он должен вернуть другой объект. Использование памяти оптимизировано. И это дефакто-путь на таких языках, как Haskell.

+0

Спасибо, вам ответить. Есть ли какое-либо решение проблемы, чтобы приведенный выше код работал правильно, как предполагалось? Я не могу себе представить, что в Python нет возможности решить проблему. Могу ли я взять другой подход или есть обходное решение для этого? Заранее спасибо! – metaphysicalmarty

0

Я нашел решение моей проблемы:

import sys 
import json 
import base64 

class BinaryToBase64Encoder(json.JSONEncoder): 
    def default(self, o): 
     if isinstance(o, bytes): 
      return base64.b64encode(o).decode("ascii") 
     return super(BinaryToBase64Encoder, self).default(o) 


def main(): 

    test_dict = { 
     "foo": [1, 3, 4, 5, 6, 7], 
     "bar": 1, 
     "baz": (1, 2), 
     "blub": { 
      "bla": b"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41", 
      "ble": { 
       "blu": [ 
        1, 3, b"\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42\x42", 
        (1, [b"\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43\x43"]) 
       ] 
      } 
     } 
    } 

    print(json.dumps(test_dict, cls=BinaryToBase64Encoder)) 

    return 0 


if __name__ == "__main__": 
    sys.exit(main()) 

Выход JSON является:

{ 
    "foo": [1, 3, 4, 5, 6, 7], 
    "baz": [1, 2], 
    "bar": 1, 
    "blub": { 
     "ble": { 
      "blu": [ 
       1, 
       3, 
       "QkJCQkJCQkJCQkJCQkJCQkJCQkI=", 
       [ 
        1, 
        ["Q0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0M="] 
       ] 
      ] 
     }, 
     "bla": "QUFBQUFBQUFBQUFBQUFBQUFBQUE=" 
    } 
} 
Смежные вопросы