Python 3으로 Python 2 객체 언 클링


129

Python 2.4에서 Python 3.4로 절인 객체를로드하는 방법이 있는지 궁금합니다.

대량의 회사 레거시 코드에서 2to3을 실행하여 최신 상태로 유지했습니다.

이 작업을 수행하면 파일을 실행할 때 다음 오류가 발생합니다.

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
    d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

경쟁에 절인 객체를 보면, 그것은있어 dictA의 dict유형의 키와 값을 포함 str.

그래서 내 질문은 : 파이썬 3.4에서 원래 python 2.4에서 절인 객체를로드하는 방법이 있습니까?


1
Python 2.4에 json모듈이 있습니까? 아마도 객체를 선택 해제하고 json 객체로 저장하는 2.4 스크립트를 작성한 다음 json 객체를 읽고 3.4 호환 피클 객체로 저장하는 3.4 스크립트를 작성할 수 있습니다. 이것은 모든 피클 파일에서 한 번만 수행하는 작업입니다.
케빈

나는이 내가 그냥 파일에 sys.stdout을 변경하고 그들을 밖으로 인쇄 할 수있다라고 생각 dicts이 점을 고려, 비슷한 라인을 따라 생각하고 있었다, 그러나 나는 내가 먼저로드 할 수 있는지보고 싶어
NDevox

관련 질문은 날짜 / 시간과 관련이 있습니다. stackoverflow.com/questions/24805105/…
John Y

답변:


189

pickle.load()파이썬 pickle바이트 문자열 데이터를 파이썬 3 문자열로 변환하는 방법 을 알려주 거나 바이트로 남겨 둘 수 있습니다.

기본값은 모든 문자열 데이터를 ASCII로 시도하고 디코딩하는 것이며 해당 디코딩에 실패합니다. pickle.load()설명서를 참조하십시오 :

선택적 키워드 인수는 fix_imports , encodingerrors 이며, 이는 Python 2에서 생성 된 피클 스트림에 대한 호환성 지원을 제어하는 ​​데 사용됩니다. fix_imports 가 true 인 경우 pickle은 이전 Python 2 이름을 Python 3에서 사용 된 새 이름으로 맵핑하려고 시도합니다. 인코딩오류 는 피클에게 파이썬 2에 의해 절인 8 비트 문자열 인스턴스를 디코딩하는 방법을 알려줍니다. 이들은 각각 'ASCII'및 'strict'로 설정됩니다. 인코딩 바이트 개체로이 8 비트 문자열 인스턴스를 읽기 '바이트'가 될 수 있습니다.

인코딩을 설정하면 latin1데이터를 직접 가져올 수 있습니다.

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

그러나 잘못된 코덱을 사용하여 문자열을 디코딩하지 않았는지 확인해야합니다. Latin-1은 바이트 값 0-255를 첫 번째 256 개의 유니 코드 코드 포인트에 직접 매핑하므로 모든 입력에서 작동합니다.

대안은로 데이터를로드하고 나중에 encoding='bytes'모든 bytes키와 값을 디코딩하는 것 입니다.

3.6.8, 3.7.2 및 3.8.0 이전의 Python 버전까지는 Python 2 datetime객체 데이터의 피클 링 이 사용하지 않으면 중단 됩니다 encoding='bytes'.


1
어떻게 파이썬 2와 호환이 가능합니까? 분명히, 인수를 인코딩하는 것은 파이썬 2에 존재하지 않는
EpicAdv

2
@EpicAdv :이 코드를 Python 2와 호환되도록 만들 필요는 없습니다. 이 질문은 Python 2 피클을 Python 3에로드하는 방법에 관한 것입니다. Python 2 encoding용 키워드를 모두 삭제하십시오 .
Martijn Pieters

10
@EpicAdv : python 2에 비어 있거나 'encoding': 'latin1'pickle_options를 pickle로 보내는 pickle_options 사전을 만들 수 있습니다 . 이 방법으로 두 버전 모두에서 실행해야합니다.
pipefish

@pipefish-영리하지만 어딘가에서 사용중인 버전을 감지해야하므로 버전에 따라 다른 방식으로 (추가 인수가없는 것과 다른 인수를 사용하여) 더 간단하게 호출 할 수도 있습니다. 그러나 적어도 당신은 Martijn의 의견이 전혀 다루지 않은 EpicAdv의 의견을 얻었습니다.
John Y

2
나는 그 datetime의견 이이 답변의 주요 추진력이 아니라는 것을 알고 있지만, 미래 독자들을 위해 Python 3의 "고정 된"버전조차도 여전히 encoding='latin-1'Python 2 날짜 시간을 피클 링 해야한다고 지적하고 싶습니다 . 절인 Python 2 데이터에 Latin-1 이외의 것으로 인코딩 된 날짜 시간과 바이트 문자열이 모두 포함되어 있으면 encoding='bytes'결국 사용하는 것이 좋습니다 .
John Y

15

encoding='latin1'객체에 numpy 배열이 포함 된 경우 사용 하면 일부 문제가 발생합니다.

사용하는 encoding='bytes'것이 좋습니다.

사용에 대한 자세한 설명 은이 답변 을 참조하십시오encoding='bytes'


어떤 문제? 내가 무엇을 조심해야합니까? 를 사용 bytes하면 문자열을 bytes ()로 만들므로 latin1가능한 경우 선호 하지만 문제가 무엇인지 명확하지 않습니다.
Gulzar

2
@ sreeragh-ar : 발생한 문제의 예를 들어 주시겠습니까? numpy.ndarray파이썬 2.7에서 2를 사용하여 절인 2 차원 (numpy 1.14)을 가지고 cPickle.dumps()있으며 Python 3에서 unpickling을 사용 하면 pickle.loads(..., encoding='latin1')정상적으로 작동합니다.
djvg

@djvg 이미지를 이미지 문자열로 피클하고 피클 링해야 할 때 문제가 발생했습니다. 코드는 여기에서 찾을 수 있습니다. gist.github.com/sreeragh-ar/70205db3a43badbfa69f758faa898be3
Sreeragh AR

@Gulzar 문제에 대한 위의 요점을 참조하십시오. 산세 제거 후 이미지가 손상되었습니다.
Sreeragh AR
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.