Форум сайта python.su
Происходит ошибка при чтении раннее записанной информации из файла.
Вот проблемный кусок кода:
#!/usr/bin/python
import cPickle, struct
l
D={'user': 'password'}
im_dump=cPickle.dumps(D, -1)
length_dump=len(im_dump)
#Пишем в файл
data=str(struct.pack('>i4sh',length_dump,im_dump,8))
pass_file=open('c:\\Python26\\passwd.txt','wb')
pass_file.write(data)
pass_file.close()
print data
#Читаем из файла
pass_file=open('c:\\Python26\\passwd.txt','rb')
test_dump=pass_file.read()
print test_dump
data=str(struct.unpack('>i4sh',test_dump))
D=dict(cPickle.loads(data))
pass_file.close()
print data
Ђ}qUuserqUpasswordqs.
Traceback (most recent call last):
File "C:\Python26\mystruct.py", line 21, in <module>
D=dict(cPickle.loads(data))
UnpicklingError: unpickling stack underflow
Отредактировано (Авг. 2, 2010 21:05:43)
Офлайн
Проблема с тем, что вы пакуете 4 байта из 27 нужных. Естественно, что потом не распикливается.
In [2]: len(cPickle.dumps({'user': 'password'}, -1))
Out[2]: 27
Отредактировано (Авг. 2, 2010 20:34:33)
Офлайн
Ed, я заменил “7” на “length_dump=len(im_dump)”, мой первый пост.
Сообщение об ошибке тоже изменилось, я его вставил вместо первого.
EdЯ что то не понимаю, какие два числа, как это исправить?
а там еще 2 числа, которые там совсем не нужны.
Отредактировано (Авг. 2, 2010 21:17:29)
Офлайн
Ну давайте разбираться. Я буду задавать вопросы, а вы будете отвечать.
1. Что означает цифра 4 в ‘>i4sh’?
2. Что означает цифра 8 в struct.pack('>i4sh',length_dump,im_dump,8)
3. Зачем вы преобразовываете результат stuct.pack в строку?
4. Как вы собираетесь делать обратное преобразование, прочитав эту строку из файла?
Для начала достаточно. Жду ответов.
Офлайн
1. Понятия не имею, поэтому и спрашиваю. Документация на английском, в нем я не настолько силен, чтобы детально понять, к сожалению. В основном ориентировался русскоязычным учебником, там вкратце затрагивался struct, идея понравилась решил реализовать.
2. Аналогично.
3. Это я исправил. Но при распаковке пикл принимает только строку.
4. Словарь -> cPickle объект -> strukt -> загоняем в бинарный файл. Обратно: открываем файл -> распаковываем struct-ом -> передаем cPickle-у -> записываем в словарь. По идее пикл должен бы получить стрку в томже виде, в каком ее туда положил.
Задумка была такая, хотелось бы получить помощь в этом вопросе.
Отредактировано (Авг. 3, 2010 13:11:56)
Офлайн
naumanУпс. То есть вы написали эту стороку: data=str(struct.pack('>i4sh',length_dump,im_dump,8))
1. Понятия не имею
Задумка была такая, хотелось бы получить помощь в этом вопросе.Я и пытаюсь эту помощь оказать. Думал, что вы знаете что вы написали.
Офлайн
Если объясните, что такое >i4sh и 8, буду рад, так как думаю, что может проблема в них.
Мне важен принцип правильной работы в связке объект -> cPickle -> struct и обратно, так как он довольно часто будет употребляться. Без struct все нормально работает, т.е. когда cPickle пишет в файл.
Что касается приведенного кода. Основная, может параноидальная идея - имя и зашифрованный пароль скрыть в бинарном файле, подальше от глаз. Пикл в созданном файле отображает имя и пароль, даже если запускается с параметром -1. Я мог бы обойтись и без Пикла, но с ним гораздо удобнее.
Отредактировано (Авг. 3, 2010 14:43:19)
Офлайн
>i4sh - это формат, подразумевает упаковывание в структуру 3х объектов - целое(i), строку из 4 символов(4s) и короткое целое(h). То есть вы запаковываете в структуру целое - сначала было 7, а потом вы поменяли это на длину запикленого, строку длиной 4 (начало вашей запикленой строки) и короткое целое 8. Я поэтому и интересовался что это за волшебные цифры 7 и 8, которые вы пакуете вместе с тем, что вам нужно.
Идея в целом не параиноидальная, но не очень хорошая.
Вот смотрите что мы имеем:
это то, что выдает pickle:
In [6]: cPickle.dumps({'user': 'password'})
Out[6]: "(dp1\nS'user'\np2\nS'password'\np3\ns."
In [7]: pickled = cPickle.dumps({'user': 'password'})
In [8]: struct.pack('%ds' % len(pickled), pickled)
Out[8]: "(dp1\nS'user'\np2\nS'password'\np3\ns."
Офлайн
Этого было бы достаточно:
import hashlib
D={'user': (hashlib.md5('password').hexdigest())}
Отредактировано (Авг. 3, 2010 15:44:10)
Офлайн
Если посто хочется скрыть от шаловливых ручек пользователей (а не взлома), то гораздо проще вот так:
#!/usr/bin/env python
## o* - open
## e* - encode
## d* - decode
odata = "username:knkd\x00passwd:superpassword"
edata = odata.encode('bz2').encode('hex')
print edata
-> '425a6839314159265359f1d03e7c00000fc98040000010260bda80200021a9a68c4da6a100001f8d3e128de762cc5517490dc8a3a4c3e2ee48a70a121e3a07cf80'
ddata = edata.decode('hex').decode('bz2')
repr(ddata)
-> "'username:knkd\\x00passwd:superpassword'"
Отредактировано (Авг. 3, 2010 23:35:40)
Офлайн