เราจะแปลงการแสดงสตริง Python ของสตริงไบต์เป็นสตริงไบต์จริงได้อย่างไร [ทำซ้ำ]

ฉันกำลังพยายามคิดว่าใครจะแปลงการแสดงสตริงของสตริงไบต์เป็นประเภทสตริงไบต์จริงได้อย่างไร ฉันไม่คุ้นเคยกับ Python มากนัก (แค่แฮ็กมันเพื่อช่วยเพื่อน) ดังนั้นฉันจึงไม่แน่ใจว่ามีวิธี "แคสต์" ง่ายๆ หรือไม่ (เหมือนที่ Java ที่รักของฉันมี ;) ) โดยพื้นฐานแล้วฉันมีไฟล์ข้อความซึ่งมีเนื้อหาเป็นสตริงไบต์:

b'\x03\xacgB\x16\xf3\xe1\\v\x1e\xe1\xa5\xe2U\xf0g\x956#\xc8\xb3\x88\xb4E\x9e\x13\xf9x\xd7\xc8F\xf4'

ขณะนี้ฉันอ่านในไฟล์นี้ดังนี้:

aFile = open('test.txt')
x = aFile.read()
print(x) # prints b'\x03\xacgB\x16\xf3\xe1\\v\x1e\xe1\xa5\xe2U\xf0g\x956#\xc8\xb3\x88\xb4E\x9e\x13\xf9x\xd7\xc8F\xf4'
print(type(x)) # prints <class 'str'>

ฉันจะทำให้ x เป็นประเภท <class 'bytes'> ได้อย่างไร ขอบคุณสำหรับความช่วยเหลือใด ๆ

แก้ไข: เมื่อได้อ่านคำตอบด้านล่าง ฉันคิดว่าฉันอาจจะจำกัดคำถามมากเกินไป ฉันขอโทษสำหรับเรื่องนั้น สตริงอินพุตไม่จำเป็นต้องอยู่ในรูปแบบ python byte-string (เช่น ด้วย b และเครื่องหมายคำพูด) อาจเป็นเพียงแค่สตริงไบต์ธรรมดา:

\x03\xacgB\x16\xf3\xe1\\v\x1e\xe1\xa5\xe2U\xf0g\x956#\xc8\xb3\x88\xb4E\x9e\x13\xf9x\xd7\xc8F\xf4

หากสิ่งนี้ทำให้ง่ายขึ้นหรือเป็นการฝึกฝนที่ดีขึ้น ฉันสามารถใช้สิ่งนี้ได้


person Stephen    schedule 12.03.2011    source แหล่งที่มา
comment
ไม่มีการคัดเลือกใน Python แนวคิดนี้ไม่สมเหตุสมผลในภาษาไดนามิก มันคือการพิมพ์แบบเป็ดทั้งหมด ถ้ามันดูเหมือน str และเดินเหมือน str คุณจะถือว่ามันเป็น str แล้วคุณจะโยนสิ่งนี้อย่างไร? ถ้าคุณโยนมันไปที่ str คุณจะได้ str ที่ขึ้นต้นด้วย b'\x :)   -  person Lennart Regebro    schedule 12.03.2011


คำตอบ (2)


เนื่องจากอินพุตของคุณอยู่ในไวยากรณ์ของ Python ด้วยเหตุผลบางอย่าง (*) สิ่งที่ต้องทำที่นี่คือเพียงแค่โทร eval:

>>> r"b'\x12\x12'"
"b'\\x12\\x12'"
>>> eval(r"b'\x12\x12'")
'\x12\x12'

โปรดใช้ความระมัดระวังเนื่องจากอาจเป็นปัญหาด้านความปลอดภัย eval จะเรียกใช้โค้ด ใดๆ ดังนั้นคุณอาจต้องฆ่าเชื้ออินพุต ในกรณีของคุณมันง่าย - เพียงตรวจสอบว่าสิ่งที่คุณ eval เป็นสตริงในรูปแบบที่คุณคาดหวัง หากความปลอดภัยไม่เป็นปัญหาที่นี่ ก็อย่ากังวลไป

การแก้ไขการแก้ไขของคุณซ้ำ: ถึงกระนั้น eval เป็นวิธีที่ง่ายที่สุดที่นี่ (หลังจากเพิ่ม b'' หากไม่มี) แน่นอนว่าคุณสามารถทำได้ด้วยตนเองโดยแปลง \xXX แต่ละรายการให้เป็นมูลค่าจริง


(*) ทำไมจริงๆเหรอ? ดูเหมือนเป็นทางเลือกที่แปลกสำหรับรูปแบบการแสดงข้อมูล

person Eli Bendersky    schedule 12.03.2011
comment
เหตุผลก็คือสิ่งหนึ่งที่ฉันเพิ่งรู้ว่ามันงี่เง่าที่สุด XD. การจัดเก็บค่าแฮชเมื่อเล่น ไม่คิดว่าจะใช้ .hexdigest() แทน digest() hexdigest() แน่นอนว่าให้สายออกมา ซึ่งน่าเล่นกว่ามาก ขอโทษที่รบกวนคุณด้วยคำถามโง่ๆ - person Stephen; 12.03.2011
comment
@Stephen: ไม่เป็นไร ตราบใดที่คุณได้รับความช่วยเหลือ ;-) การมีรูปแบบเช่นนี้เป็นกลิ่นโค้ดที่ชัดเจน ดังนั้นฉันจึงชี้ให้เห็น - person Eli Bendersky; 12.03.2011
comment
@Stephen: Bytes ดีที่จะเล่นด้วย (แต่โอเคอาจจะไม่ดีเท่านี้) คำถามคือทำไมคุณถึงเขียนการแทนไบต์ลงในไฟล์แทนที่จะเป็นไบต์เอง - person Lennart Regebro; 12.03.2011

>>> r'\x03\xacgB\x16\xf3\xe1\\v\x1e\xe1\xa5\xe2U\xf0g\x956#\xc8\xb3\x88\xb4E\x9e\x13\xf9x\xd7\xc8F\xf4'.decode('string-escape')
'\x03\xacgB\x16\xf3\xe1\\v\x1e\xe1\xa5\xe2U\xf0g\x956#\xc8\xb3\x88\xb4E\x9e\x13\xf9x\xd7\xc8F\xf4'

สิ่งนี้จะใช้ได้กับสตริงที่ไม่มี b'...' ล้อมรอบ มิฉะนั้น คุณควรใช้ ast.literal_eval()

person Ignacio Vazquez-Abrams    schedule 12.03.2011
comment
ด้วยเหตุผลที่อยู่นอกเหนือฉัน ast.literal_eval() ใช้งานไม่ได้กับ b'' ตัวอักษรใน Python 3.x นั่นคือสาเหตุที่ฉันลบคำตอบ - person Sven Marnach; 12.03.2011
comment
@สเวน: แปลก ทำงานได้ดีบน 2.7 - person Ignacio Vazquez-Abrams; 12.03.2011
comment
@Sven: ฮะคุณพูดถูก คุณรู้หรือไม่ว่ามีรายงานข้อผิดพลาดแบบเปิดสำหรับสิ่งนั้นหรือไม่? - person ncoghlan; 12.03.2011
comment
@Sven: literal_eval เห็นได้ชัดว่าสามารถจัดการไบต์จาก 3.2.1 ไม่รู้ว่าทำไมมันถึงถูกละเว้นไปก่อนหน้านั้น - person Thomas K; 12.03.2011
comment
มันควรจะเป็น .decode('unicode_escape') บน Python3 - person jfs; 12.03.2011
comment
... ซึ่งจะต้องถูกเรียกใช้บนวัตถุ bytes และควรตามด้วย .encode('latin-1') เพื่อรับวัตถุ bytes ที่ต้องการ - person Miles; 14.03.2011