Форум сайта python.su
0
Приветствую сообщество! Возникла задача написать програмку для использования с Zabbix. Нужно распарсить странный json (структуру которого я не могу изменить), из-за этого использую циклы, чтобы сериализовать данные в объекты и список этих объектов сохранить в файл. Решил использовать Pickle. Но возникает ошибка в независимости от использования pickle и cPickle. Использую Python 2.7.
Определение класса:
class Switch(): """Object switch """ def __init__(self, mac="", ip="" ports = []): self.mac = mac self.ip = ip self.ports = ports
for mac in data_from_url: sw = Switch(mac) # Create instance switch_list.append(sw) # Adding object to list # Adding values to attributes of objects: if isinstance(data_from_url[mac], dict): for mac in data_from_url: if switch_key == '1': sw.ip = data_from_url[mac][switch_key] if switch_key == '21': sw.mac = data_from_url[mac][switch_key]
print object1.__dict__ {'hostname': u'name', 'ip': u'192.168.0.1' ... } print object2.__dict__ {'hostname': u'name2', 'ip': u'192.168.0.2' ... } list_objects = [object1, object2, ... ] save_to_file(list_objects, file.db) def save_to_file(lst, file_pickle): with open(file_pickle, 'wb') as output: pickle.dump(lst, output) output.close()
File "/home/thund3r/work/git/zabbix_topology/list_of_objects.py", line 89, in save_to_file pickle.dump(lst, output) File "/usr/lib/python2.7/pickle.py", line 1376, in dump Pickler(file, protocol).dump(obj) File "/usr/lib/python2.7/pickle.py", line 224, in dump self.save(obj) File "/usr/lib/python2.7/pickle.py", line 286, in save f(self, obj) # Call unbound method with explicit self File "/usr/lib/python2.7/pickle.py", line 606, in save_list self._batch_appends(iter(obj)) File "/usr/lib/python2.7/pickle.py", line 621, in _batch_appends save(x) File "/usr/lib/python2.7/pickle.py", line 286, in save f(self, obj) # Call unbound method with explicit self File "/usr/lib/python2.7/pickle.py", line 704, in save_inst args = obj.__getinitargs__() TypeError: 'str' object is not callable
for x in zabbix_switches: if x.mac == '1024CF94FD97': print x.__name__ print x.__class__ print x.__dict__
__name__ __main__.Switch {'ip': u'192.168.0.1', 'mac': u'1024CF94FD97', ...}
Офлайн
186
> Нужно распарсить странный json (структуру которого я не могу изменить), из-за этого использую циклы
Используй simplejson.
чтобы сериализовать данные в объекты и список этих объектов сохранить в файл. Решил использовать Pickle.
Зачем тебе Pickle? Храни в файле json, при необходимости его можно легко сериализовать.
Офлайн
0
Спасибо! Так как я не знаю еще модулей, вычитал, что cPickle будет работать быстрее, но прочитал о simplejson и наверное буду использовать его, темболее я уже использовал json в этой же программе, но для других целей:
response = urllib .urlopen(url) data_from_url = json.loads(response.read())
def save_to_file(data, file_json): # print(obj.__getinitargs__()) with open(file_json, 'w') as outfile: json.dumps(data, outfile) outfile.close()
Connected to pydev debugger (build 172.3544.46) Traceback (most recent call last): File "/home/thund3r/.local/share/JetBrains/Toolbox/apps/PyCharm-C/ch-0/172.3544.46/helpers/pydev/pydevd.py", line 1599, in <module> globals = debugger.run(setup['file'], None, None, is_module) File "/home/thund3r/.local/share/JetBrains/Toolbox/apps/PyCharm-C/ch-0/172.3544.46/helpers/pydev/pydevd.py", line 1026, in run pydev_imports.execfile(file, globals, locals) # execute the script File "/home/thund3r/work/git/zabbix_topology/list_of_objects.py", line 160, in <module> save_to_file(zabbix_switches, db_file) # TODO add hash compare of file File "/home/thund3r/work/git/zabbix_topology/list_of_objects.py", line 90, in save_to_file json.dumps(data, outfile) File "/home/thund3r/.local/lib/python2.7/site-packages/simplejson/__init__.py", line 397, in dumps **kw).encode(obj) File "/home/thund3r/.local/lib/python2.7/site-packages/simplejson/encoder.py", line 291, in encode chunks = self.iterencode(o, _one_shot=True) File "/home/thund3r/.local/lib/python2.7/site-packages/simplejson/encoder.py", line 373, in iterencode return _iterencode(o, 0) File "/home/thund3r/.local/lib/python2.7/site-packages/simplejson/encoder.py", line 268, in default raise TypeError(repr(o) + " is not JSON serializable") TypeError: 'str' object is not callable
json.dumps(data, outfile)
for x in zabbix_switches: if x.mac == '23AAFC94FD95': print x.__name__ print x.__class__ print x.__dict__
__name__ __main__.Switch {'building': '1', 'hostname': '3528', 'monitoring': '0', 'porch': '0', 'ip': '192.168.0.1', 'vlan': '0', 'snmp_write': 'smp-wr', 'ports': [<__main__.Port instance at 0x000009e02d8>], 'mac': '23AAFC94FD95', 'street': u'043d\u0438\u0446\u044c\u043a\u043e\u0457 \u0421\u043e\u043b', 'floor': '0', 'inventory_state': '1', 'model': 'EdgeCore_ES3528M', 'serial': '0000001'} {'upswitch_mac': '0004968BC143', 'upswitch_port': '6', 'num': '1', 'port': '28'}
Отредактировано thund3r (Сен. 16, 2017 12:04:21)
Офлайн
221
Вам бы кашу эту убрать и оставить все что по сути. Вот вы собрали некие данные data, покажите что это.
P.S. вы понимаете что в JSON могут быть сохранены только примитивные типы данных?
Офлайн
0
В data передовал словарь объектов.
Да, Вы правы! Я не понял, что нельзя прямо сериализовать объект! На сколько я понял можно только его __dict__.
Спасибо!
Кажется как сериализовать объект я понял. Но вот как правильно сериализовать словарь объектов, а в дальнейшем десериализовать в тот же словарь - еще нет, и пока не нашел решения в интернете. Подскажите, пожалуйста или может есть ссылка?
Сейчас сделал:
def save_to_file(data): with open(db_file, 'w') as outfile: for key, obj in data.iteritems(): outfile.write(json.dumps(obj, default=lambda o: o.__dict__)) outfile.close()
Офлайн
221
А собственно изначально вы этого хотели?
In [2]: class Switch(): ...: def __init__(self, mac="", ip="", ports = []): ...: self.mac = mac ...: self.ip = ip ...: self.ports = ports ...: In [3]: sw1 = Switch('mac1', 'ip1', [1001, 1002]) In [4]: sw2 = Switch() In [5]: sw2.mac = 'mac2' In [6]: sw2.ip= 'ip2' In [8]: sw2.ports = [2001] In [9]: sw_list = [sw1, sw2] In [10]: import pickle In [11]: with open('sws.pickle', 'wb') as f: ....: pickle.dump(sw_list, f) ....: In [12]: with open('sws.pickle', 'rb') as f: ....: sw_p = pickle.load(f) ....: In [13]: sw_list == sw_p Out[13]: False In [14]: sw_list Out[14]: [<__main__.Switch at 0x7f8a4327a438>, <__main__.Switch at 0x7f8a4327a390>] In [15]: sw_p Out[15]: [<__main__.Switch at 0x7f8a432575f8>, <__main__.Switch at 0x7f8a432577f0>] In [16]: [x.__dict__ for x in sw_list] Out[16]: [{'mac': 'mac1', 'ports': [1001, 1002], 'ip': 'ip1'}, {'mac': 'mac2', 'ports': [2001], 'ip': 'ip2'}] In [17]: [x.__dict__ for x in sw_list] == [x.__dict__ for x in sw_p] Out[17]: True
Офлайн
0
Простите, что не сразу отвечаю - хотелось уже все проверить и поправить
Совершенно верно. Только я допустил несколько ошибок…
Да, и если сохранять коммандой
outfile.write(json.dumps(x.__dict__ for x in data))
raise TypeError(repr(o) + " is not JSON serializable") TypeError: <generator object <genexpr> at 0x7f7d543f40f0> is not JSON serializable
If specified, default should be a function that gets called for objects that can’t otherwise
be serialized. It should return a JSON encodable version of the object or raise a TypeError.
If not specified, TypeError is raised.
def save_to_file(data, file_to_save): with open(file_to_save, 'w') as outfile: for obj in data: outfile.write(json.dumps(obj, default=lambda o: o.__dict__)) outfile.close()
class Switch: ... def toJSON(self): return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) def save_to_file(data, file_to_save): with open(file_to_save, 'w') as outfile: for obj in data: outfile.write(json.dumps(obj.toJSON())) outfile.close()
class Switch: def __init__(self, mac="", ip="", ports = []): self.mac = mac self.ports = []
for mac in data_from_url: sw = Switch(mac) switch_dict.append(sw) for port in data_from_url[mac][switch_key] pt = Port(port) sw.ports.append(pt)
Отредактировано thund3r (Сен. 17, 2017 01:10:52)
Офлайн