การปลดวัตถุ python 2 ด้วย python 3


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)

เมื่อมองไปที่วัตถุดองในการโต้แย้งมันเป็นdictใน a dictที่มีคีย์และค่าประเภทstrที่มีคีย์และค่าประเภท

คำถามของฉันคือ: มีวิธีโหลดวัตถุเดิมที่ดองใน python 2.4 ด้วย python 3.4 หรือไม่?


1
Python 2.4 มีjsonโมดูลหรือไม่ บางทีคุณอาจเขียนสคริปต์ 2.4 ที่ยกเลิกการตรึงวัตถุและบันทึกเป็นวัตถุ json จากนั้นเขียนสคริปต์ 3.4 ที่อ่านวัตถุ json และบันทึกเป็นวัตถุดองที่เข้ากันได้ 3.4 นี่จะเป็นการดำเนินการครั้งเดียวที่คุณเรียกใช้กับไฟล์ดองทั้งหมดของคุณ
Kevin

ฉันกำลังคิดตามแนวเดียวกันโดยพิจารณาว่าสิ่งเหล่านี้เป็นคำสั่งฉันคิดว่าฉันสามารถเปลี่ยน sys.stdout เป็นไฟล์และพิมพ์ออกมาได้ แต่ฉันต้องการดูว่าฉันสามารถโหลดได้ก่อนหรือไม่
NDevox

คำถามที่เกี่ยวข้องเกี่ยวข้องกับวันที่โดยเฉพาะ: stackoverflow.com/questions/24805105/…
John Y

คำตอบ:


189

คุณจะต้องบอกpickle.load()วิธีการแปลงข้อมูลการทดสอบโดย Python เป็นสตริง Python 3 หรือคุณสามารถบอกpickleให้ปล่อยให้เป็นไบต์

ค่าเริ่มต้นคือการพยายามและถอดรหัสข้อมูลสตริงทั้งหมดเป็น ASCII และการถอดรหัสล้มเหลว ดูpickle.load()เอกสารประกอบ :

ข้อโต้แย้งคำหลักที่เป็นตัวเลือกที่มีfix_imports , การเข้ารหัสและข้อผิดพลาดซึ่งจะใช้ในการสนับสนุนการควบคุมการทำงานร่วมกันสำหรับกระแสดองสร้างโดยงูหลาม 2. หากfix_importsเป็นความจริงดองจะพยายามที่จะแมเก่างูหลาม 2 ชื่อชื่อใหม่ที่ใช้ในหลาม 3. การเข้ารหัสและข้อผิดพลาดบอกวิธีการถอดรหัสอินสแตนซ์สตริง 8 บิตที่ดองโดย Python 2 ค่าเริ่มต้นเหล่านี้เป็น "ASCII" และ "เข้มงวด" ตามลำดับ การเข้ารหัสสามารถเป็น 'ไบต์' เพื่ออ่านอินสแตนซ์สตริง 8 บิตเหล่านี้เป็นไบต์ออบเจ็กต์

การตั้งค่าการเข้ารหัสเพื่อlatin1ให้คุณนำเข้าข้อมูลได้โดยตรง:

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

แต่คุณจะต้องตรวจสอบว่าไม่มีการถอดรหัสสตริงของคุณโดยใช้ตัวแปลงสัญญาณที่ไม่ถูกต้อง Latin-1 ทำงานสำหรับอินพุตใด ๆ เนื่องจากแมปค่าไบต์ 0-255 กับ 256 Unicode codepoints แรกโดยตรง

อีกทางเลือกหนึ่งคือการโหลดข้อมูลencoding='bytes'และถอดรหัสทั้งหมดbytesคีย์และค่าทั้งหมดในภายหลัง

โปรดทราบว่าขึ้นอยู่กับรุ่นก่อน Python 3.6.8, 3.7.2 และ 3.8.0, unpickling ของงูใหญ่ 2 datetimeข้อมูลของวัตถุเสียencoding='bytes'เว้นแต่คุณจะใช้


1
สิ่งนี้จะทำให้เข้ากันได้กับ Python 2 แบบย้อนหลังได้อย่างไร เห็นได้ชัดว่าไม่มีอาร์กิวเมนต์การเข้ารหัสสำหรับ Python 2
EpicAdv

2
@EpicAdv: คุณไม่จำเป็นต้องทำให้รหัสนี้เข้ากันได้กับ Python 2 คำถามนี้เกี่ยวกับวิธีโหลด Python 2 ดองลงใน Python 3 วางencodingคีย์เวิร์ดทั้งหมดสำหรับ Python 2
Martijn Pieters

10
@EpicAdv: คุณสามารถสร้างพจนานุกรม pickle_options ที่ว่างสำหรับ python 2 หรือมี'encoding': 'latin1'และส่ง ** pickle_options ไปยังดอง วิธีนี้ควรทำงานในทั้งสองเวอร์ชัน
pipefish

@pipefish - ฉลาด แต่บางแห่งคุณต้องตรวจจับว่าคุณกำลังใช้เวอร์ชันใดอยู่ดังนั้นคุณจึงสามารถเรียกได้อย่างตรงไปตรงมามากขึ้นเพียงแค่ทำการโทรที่แตกต่างกัน (หนึ่งกับและอีกครั้งโดยไม่มีอาร์กิวเมนต์เพิ่มเติม) ขึ้นอยู่กับเวอร์ชัน แต่อย่างน้อยคุณก็มีส่วนสำคัญของความคิดเห็นของ EpicAdv ซึ่งความคิดเห็นของ Martijn ไม่ได้กล่าวถึงเลย
John Y

2
ฉันตระหนักดีdatetimeว่าความคิดเห็นไม่ใช่แรงผลักดันหลักของคำตอบนี้ แต่สำหรับผู้อ่านในอนาคตฉันอยากจะชี้ให้เห็นว่าแม้แต่ Python 3 เวอร์ชัน "คงที่" ก็ยังต้องencoding='latin-1'ยกเลิกวันที่ของ Python 2 ถ้างูหลาม 2 ข้อมูลดองของคุณเกิดขึ้นรวมทั้ง datetimes และ bytestrings เข้ารหัสในสิ่งอื่นที่ไม่ใช่ภาษาละติน-1 แล้วคุณยังอาจจะดีกว่าการใช้encoding='bytes'หลังจากทั้งหมด
John Y

15

การใช้ encoding='latin1'ทำให้เกิดปัญหาบางอย่างเมื่อวัตถุของคุณมีอาร์เรย์จำนวนนับอยู่ในนั้น

การใช้ encoding='bytes'จะดีกว่า

โปรดดูคำตอบนี้สำหรับคำอธิบายที่สมบูรณ์เกี่ยวกับการใช้encoding='bytes'


ประเด็นไหน? ควรระวังอะไรบ้าง? การใช้bytesทำให้สตริงเป็นไบต์ () ดังนั้นฉันชอบlatin1ถ้าเป็นไปได้ แต่ไม่ชัดเจนสำหรับฉันว่าปัญหาคืออะไร
Gulzar

2
@ sreeragh-ar: คุณช่วยยกตัวอย่างปัญหาที่คุณพบได้หรือไม่? ฉันมีสองมิติnumpy.ndarray(numpy 1.14) ที่ดองใน Python 2.7 โดยใช้cPickle.dumps()และการยกเลิกการตรึงใน Python 3 โดยใช้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.