การบันทึก Python ติดอยู่บนไบต์เฉพาะ - 0x90

ฉันเจอปัญหาที่แปลกประหลาดมาก และฉันก็ไม่รู้ว่าจะต้องทำอย่างไรกับมันจริงๆ เลยตัดสินใจถามไปทั่ว เรื่องสั้นยาว เมื่อฉันพยายามบันทึกไบต์ 0x90 ใน logging.Logger ของฉัน มันทำให้เทอร์มินัล Python ทั้งหมดค้าง จากไบต์ทั้งหมดที่ฉันได้ลอง (ASCII ทั้งหมดและไบต์อื่น ๆ อีกมากมายด้วย) นี่เป็นเพียงไบต์เดียวที่แสดงพฤติกรรมนี้ ดูด้านล่างสำหรับรายละเอียดเพิ่มเติม

บริบทเล็กน้อย

ฉันมีแอปพลิเคชัน WX ที่รับข้อมูลจากพอร์ตอนุกรม แสดงผลและบันทึกข้อมูล การรับข้อมูลจากพอร์ตได้รับการจัดการโดยแบ็กเอนด์ ซึ่งฉันได้ทดสอบอย่างกว้างขวางผ่านการทดสอบหน่วย ฉันค่อนข้างแน่ใจว่ามันใช้งานได้ ทั้งเมื่อฉันใช้ "bent pipe" เพื่อส่ง/รับไบต์ และเมื่อฉันใช้ Arduino เพื่อส่งไบต์ไปยังแอป ดูเหมือนว่าแอป frontend=the WX จะใช้งานได้ เช่น แสดงไบต์ที่ได้รับและบันทึกไว้ใน logging.Logger

ปัญหาเฉพาะ

ฉันพยายามทำซ้ำการทดสอบแบ็กเอนด์หน่วยทั้งหมดของฉันเป็นการทดสอบกล่องดำของแอปทั้งหมด ทุกอย่างทำงานได้ดียกเว้นกรณีเดียวซึ่งส่งหลายไบต์ รวมถึง 0x90 = 58256 = 'ã' ฉันประหลาดใจเมื่อได้รับไบต์นี้ logging.Logger จะหยุดแสดงข้อความเพิ่มเติม อย่างไรก็ตามแอปยังคงดำเนินต่อไปอย่างมีความสุข

สิ่งที่ฉันได้ลองและผลลัพธ์

คนน่าสงสาร ดูเหมือนว่าจะมีปัญหากับไบต์เดียวกันแต่ไม่มีการตอบกลับใดๆ พวกเขามีปัญหาที่คล้ายกันที่นี่ แต่ไม่ได้กล่าวถึงข้อมูลเฉพาะใดๆ โดยรวมแล้ว ดูเหมือนจะไม่มีอะไรพิเศษเกี่ยวกับ 0x90 ใช่ไหม?

ฉันได้จำกัดปัญหาให้เหลือเพียงเครื่องมืออำนวยความสะดวกในการบันทึก โปรดดู MWE ด้านล่าง หากฉันเรียกใช้ MWE จากเทอร์มินัล มันก็จะเสร็จสิ้นโดยไม่มีปัญหา เหมือนกันถ้าฉันเรียกใช้จากล่าม Python หรือ IPython ภายใน Anaconda ผลลัพธ์คือ:

.../tests$ python3 ./mwe.py 
0.5.1.2
(3, 5, 4)
2020-01-19 20:15:49,184 - MyLog - INFO - j
2020-01-19 20:15:49,184 - MyLog - INFO - 

อย่างไรก็ตาม ถ้าฉันเปิดล่าม Python แล้วรัน MWE ทีละบรรทัด ในที่สุดมันจะค้างทันทีที่ฉันพยายามบันทึก 0x90 ดูเหมือนว่าจะไม่มีวิธีปลดบล็อกเทอร์มินัล แม้จะกด Ctrl+C ก็ตาม ฉันแค่ต้องฆ่ากระบวนการล่าม

มีความคิดอะไรบ้างที่กำลังเกิดขึ้น? ขอบคุณมากสำหรับการดูสิ่งนี้

กฟผ

import logging, sys
print(logging.__version__)
# 0.5.1.2
print(sys.version_info[:3])
# (3, 5, 4)
logger = logging.getLogger("MyLog")
handler = logging.StreamHandler()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
handler.setLevel(logging.INFO)
logger.addHandler(handler)
logger.info(chr(0x6a))
# 2020-01-18 20:39:00,696 - MyLog - INFO - j
logger.info(chr(0x90))
# 2020-01-18 20:39:07,617 - MyLog - INFO -
# Python console is stalled from now-on.

สารละลาย

วิธีแก้ปัญหาที่หรูหราซึ่งกลายเป็นเกี่ยวกับการฆ่าเชื้อสตริงจากอักขระควบคุมนั้นอยู่ใน โพสต์นี้


person Aleksander Lidtke    schedule 19.01.2020    source แหล่งที่มา
comment
โปรดทราบว่าสิ่งนี้ไม่เกี่ยวข้องกับการบันทึก ลองเริ่มเซสชันหลามแบบโต้ตอบและ print(chr(0x90)) ควรทำลายเทอร์มินัลของคุณในทำนองเดียวกัน   -  person blues    schedule 20.01.2020


คำตอบ (1)


สิ่งนี้เกิดขึ้นเนื่องจากคอนโซล python มองว่าสิ่งนี้เป็นอักขระควบคุมพิเศษสำหรับเทอร์มินัลอย่างไม่เหมาะสม โดยเฉพาะอย่างยิ่งมันเริ่มต้น สตริงการควบคุมอุปกรณ์ และสิ่งเหล่านี้จำเป็นต้องถูกยกเลิก ไม่เช่นนั้นเทอร์มินัลจะ แขวน. ในการตรวจสอบให้ลองดำเนินการ print(chr(0x90)) หรือ print(chr(0x90)+chr(0x9C)) ในคอนโซลหลาม อันที่สองจะไม่ทำอะไรเลยเนื่องจากมีการสิ้นสุด 0x9c ไบต์ในขณะที่อันแรกจะหยุดทำงาน

person blues    schedule 20.01.2020
comment
ขอบคุณมาก @blues ! ไม่เคยคิดเรื่องนี้เลย เพื่อให้แอปพลิเคชันของฉันไม่ปลอดภัย คุณคิดว่าฉันควรจับตาดูสตริงควบคุมเหล่านั้นทั้งหมด และตรวจสอบให้แน่ใจว่าฉันแยกพวกมันออกจากกันหรือไม่ มีรายการสตริงควบคุมในตัว Python หรือไม่ - person Aleksander Lidtke; 20.01.2020