Рассыпать рассол Python 2 в Python 3 - PullRequest
0 голосов
/ 14 июля 2020

В рамках рабочего процесса для анализа данных я использовал dill некоторые сложные структуры, содержащие данные (в numpy массивах), а также лямбда-функции. Я без проблем работал с этой базой. Моя кодовая база находится в Python 2, но я хочу обновить ее и преобразовать в Python 3.

Теперь, когда я попытался загрузить базу данных в Python 3, я обнаружил проблемы. На первый взгляд проблема была похожа на этот вопрос . Однако изменение кодировки "latin1" не работает, и мне нужно было использовать кодировку "bytes". Тем не менее, когда я запускаю следующий код (CMIPprocs является модульной частью моей кодовой базы), впереди еще больше проблем:

import dill as pickle
import sys
sys.path.insert(0,"/Users/m300556/CMIP5_fin/Scripts/CMIPprocs")
import CMIPprocs as cmip

with open("../CMIP5_fin/Outputs/CMIP5.dict","rb") as f:
 h=pickle.load(f,encoding="bytes")

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-2-e04ea9af05f6> in <module>
      1 with open("../CMIP5_fin/Outputs/CMIP5.dict","rb") as f:
----> 2  h=pickle.load(f,encoding="bytes")

~/miniconda3/envs/glamdring/lib/python3.8/site-packages/dill/_dill.py in load(file, ignore, **kwds)
    268 def load(file, ignore=None, **kwds):
    269     """unpickle an object from a file"""
--> 270     return Unpickler(file, ignore=ignore, **kwds).load()
    271 
    272 def loads(str, ignore=None, **kwds):

~/miniconda3/envs/glamdring/lib/python3.8/site-packages/dill/_dill.py in load(self)
    470 
    471     def load(self): #NOTE: if settings change, need to update attributes
--> 472         obj = StockUnpickler.load(self)
    473         if type(obj).__module__ == getattr(_main_module, '__name__', '__main__'):
    474             if not self._ignore:

~/miniconda3/envs/glamdring/lib/python3.8/site-packages/dill/_dill.py in _load_type(name)
    575 
    576 def _load_type(name):
--> 577     return _reverse_typemap[name]
    578 
    579 def _create_type(typeobj, *args):

KeyError: b'CodeType'

Ошибка ключа b'CodeType' сообщает мне, что кодировка "bytes" меняет кое-что, связанное с этим вопросом . Уровень этого решения выходит за рамки моих знаний о Python, и я попробовал наивную модификацию решения, только чтобы закончиться другой ошибкой:

import dill as pickle
pickle._dill._reverse_typemap[b'CodeType']=type
import sys
sys.path.insert(0,"/Users/m300556/CMIP5_fin/Scripts/CMIPprocs")
import CMIPprocs as cmip

with open("../CMIP5_fin/Outputs/CMIP5.dict","rb") as f:
 h=pickle.load(f,encoding="bytes")

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-e04ea9af05f6> in <module>
      1 with open("../CMIP5_fin/Outputs/CMIP5.dict","rb") as f:
----> 2  h=pickle.load(f,encoding="bytes")

~/miniconda3/envs/glamdring/lib/python3.8/site-packages/dill/_dill.py in load(file, ignore, **kwds)
    268 def load(file, ignore=None, **kwds):
    269     """unpickle an object from a file"""
--> 270     return Unpickler(file, ignore=ignore, **kwds).load()
    271 
    272 def loads(str, ignore=None, **kwds):

~/miniconda3/envs/glamdring/lib/python3.8/site-packages/dill/_dill.py in load(self)
    470 
    471     def load(self): #NOTE: if settings change, need to update attributes
--> 472         obj = StockUnpickler.load(self)
    473         if type(obj).__module__ == getattr(_main_module, '__name__', '__main__'):
    474             if not self._ignore:

TypeError: type() takes 1 or 3 arguments

Обновить

Я обнаружил, что установив

import dill as pickle
pickle._dill._reverse_typemap[b'CodeType']=pickle._dill._reverse_typemap['CodeType']

Теперь сообщение TypeError: an integer is required (got type bytes). Этот факт побудил меня поискать дополнительную информацию о том, что такое CodeType, и обнаружил, что конструктор в Python 3.8 (версия, которую я использую) имеет дополнительный целочисленный аргумент (см. this ). Таким образом, основная проблема, я подозреваю, не в кодировке, а в конструкторе CodeType. Я не знаю, как это решить. Пожалуйста, я очень прошу вашей помощи.

Обновление 2

Открыв исходный pickle в Python 2 и удалив некоторые лямбда-функции, которые у меня были, и снова засолить его , Я могу загрузить его в Python 3. Однако это не желаемый способ действия. Это подтверждает, что проблема именно в том, о чем я подозревал при первом обновлении.

...