панды.Фрейм данных.загрузка/сохранение между вместо python2 и питон3: протокол огурчик

Я не понял, как сделать рассольную загрузку/сохранение между python 2 и 3 с фреймами данных pandas. В пиклере есть опция "протокол", с которой я играл безуспешно, но я надеюсь, что у кого-то есть быстрая идея для меня попробовать. Вот код, чтобы получить ошибку:

вместо python2.7

>>> import pandas; from pylab import *
>>> a = pandas.DataFrame(randn(10,10))
>>> a.save('a2')
>>> a = pandas.DataFrame.load('a2')
>>> a = pandas.DataFrame.load('a3')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/pandas-0.10.1-py2.7-linux-x86_64.egg/pandas/core/generic.py", line 30, in load
    return com.load(path)
  File "/usr/local/lib/python2.7/site-packages/pandas-0.10.1-py2.7-linux-x86_64.egg/pandas/core/common.py", line 1107, in load
    return pickle.load(f)
ValueError: unsupported pickle protocol: 3

питон3

>>> import pandas; from pylab import *
>>> a = pandas.DataFrame(randn(10,10))
>>> a.save('a3')
>>> a = pandas.DataFrame.load('a3')
>>> a = pandas.DataFrame.load('a2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.3/site-packages/pandas-0.10.1-py3.3-linux-x86_64.egg/pandas/core/generic.py", line 30, in load
    return com.load(path)
  File "/usr/local/lib/python3.3/site-packages/pandas-0.10.1-py3.3-linux-x86_64.egg/pandas/core/common.py", line 1107, in load
    return pickle.load(f)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf4 in position 0: ordinal not in range(128)

может быть, ожидая, что рассол будет работать между версией python, немного оптимистично?

3 ответов


У меня была та же проблема. Вы можете изменить протокол файла рассола dataframe со следующей функцией в python3:

import pickle
def change_pickle_protocol(filepath,protocol=2):
    with open(filepath,'rb') as f:
        obj = pickle.load(f)
    with open(filepath,'wb') as f:
        pickle.dump(obj,f,protocol=protocol)

тогда вы сможете открыть его в python2 без проблем.


если кто-то использует pandas.DataFrame.to_pickle() затем выполните следующие изменения в исходном коде, чтобы иметь возможность установки протокола рассола:

1) в исходном файле /pandas/io/pickle.py (перед модификацией скопируйте исходный файл как /pandas/io/pickle.py.ori) поиск следующих строк:

def to_pickle(obj, path):

pkl.dump(obj, f, protocol=pkl.HIGHEST_PROTOCOL)

изменить эти строки:

def to_pickle(obj, path, protocol=pkl.HIGHEST_PROTOCOL):

pkl.dump(obj, f, protocol=protocol)

2) в исходном файле /pandas/core/generic.py (перед модификацией скопируйте исходный файл как /pandas/core/generic.py.ori) поиск для следующих строк:

def to_pickle(self, path):

return to_pickle(self, path)

изменить эти строки:

def to_pickle(self, path, protocol=None):

return to_pickle(self, path, protocol)

3) перезапустите ядро python, если оно работает, затем сохраните фрейм данных с помощью любого имеется протокол рассольник (0, 1, 2, 3, 4):

# Python 2.x can read this
df.to_pickle('my_dataframe.pck', protocol=2)

# protocol will be the highest (4), Python 2.x can not read this
df.to_pickle('my_dataframe.pck')

4) после обновления pandas повторите шаг 1 & 2.

5) (опционально) попросите разработчиков иметь эту возможность в официальных выпусках (потому что ваш код будет бросать исключение для любых других сред Python без этих изменений)

хороший день!


вы можете переопределить самый высокий протокол, доступный для пакета рассола:

import pickle as pkl
import pandas as pd
if __name__ == '__main__':
    # this constant is defined in pickle.py in the pickle package:"
    pkl.HIGHEST_PROTOCOL = 2
    # 'foo.pkl' was saved in pickle protocol 4
    df = pd.read_pickle(r"C:\temp\foo.pkl")

    # 'foo_protocol_2' will be saved in pickle protocol 2 
    # and can be read in pandas with Python 2
    df.to_pickle(r"C:\temp\foo_protocol_2.pkl")

Это определенно не элегантное решение, но оно делает работу без изменения кода панды напрямую.

обновление: я обнаружил, что более новая версия pandas, позволяет указать версию рассола в