如何在 Python 中使用自定义错误处理程序处理编码和解码?

问题描述 投票:0回答:2

我正在研究一个场景,我需要使用 Python 中的自定义错误处理来处理字符串的编码和解码。具体来说,我想创建一个可以处理编码和解码异常的错误处理程序。

编码过程:

我已经实现了一个自定义错误处理程序

utf8_hex_replace
,它将无法以指定编码进行编码的字符转换为其 UTF-8 十六进制表示形式。当将像
'Hello, 世界'
这样的字符串编码为 ASCII 字节字符串时,这种方法效果很好,并且非 ASCII 字符将被替换为相应的 UTF-8 十六进制值。

这是我目前拥有的代码:

import codecs

def utf8_hex_replace(exception):
    if isinstance(exception, UnicodeEncodeError):
        replacement = f"[{exception.object[exception.start].encode('UTF-8').hex(' ').upper()}]"
        next_pos = exception.start + 1
        return replacement, next_pos
    else:
        raise exception  # Re-raise if it's another type of error

codecs.register_error('utf8hexreplace', utf8_hex_replace)

text = 'Hello, 世界'

encoded_utf8hexreplace = text.encode('ASCII', errors='utf8hexreplace')
print(encoded_utf8hexreplace)

这会导致:

b'Hello, [E4 B8 96][E7 95 8C]'

问题:

我可以扩展这个

utf8_hex_replace
函数来处理解码吗?我想将字节字符串
b'Hello, [E4 B8 96][E7 95 8C]'
解码回原始字符串
'Hello, 世界'
。具体来说,我想在
elif
中添加一个
utf8_hex_replace
分支,它可以捕获
UnicodeDecodeError
并将十六进制编码值解码回原始字符。

当前的方法是否可以做到这一点,或者在这种情况下是否有更好的方法来处理编码和解码?

任何指导或示例将不胜感激!

python error-handling encoding decoding codec
2个回答
0
投票

是的,您可以在解码过程中处理

UnicodeDecodeError
并正确解释编码的十六进制值

import codecs
import re

def utf8_hex_replace(exception):
    if isinstance(exception, UnicodeEncodeError):
        replacement = f"[{exception.object[exception.start].encode('UTF-8').hex(' ').upper()}]"
        next_pos = exception.start + 1
        return replacement, next_pos
    elif isinstance(exception, UnicodeDecodeError):
        # Extract the problematic part of the input
        problematic_bytes = exception.object[exception.start:exception.end]
        hex_pattern = re.match(rb'\[([0-9A-F ]+)\]', problematic_bytes)
        if hex_pattern:
            hex_bytes = bytes.fromhex(hex_pattern.group(1).decode())
            replacement = hex_bytes.decode('UTF-8')
            next_pos = exception.start + len(hex_pattern.group(0))
            return replacement, next_pos
        else:
            raise exception
    else:
        raise exception

codecs.register_error('utf8hexreplace', utf8_hex_replace)

# Test encoding
text = 'Hello, 世界'
encoded_utf8hexreplace = text.encode('ASCII', errors='utf8hexreplace')
print(encoded_utf8hexreplace)  # b'Hello, [E4 B8 96][E7 95 8C]'

# Test decoding
# Assuming the encoded string uses the same [XX XX ...] format for non-ASCII characters
decoded_utf8hexreplace = encoded_utf8hexreplace.decode('ASCII', errors='utf8hexreplace')
print(decoded_utf8hexreplace)  # 'Hello, 世界'

0
投票

谢谢的回复。尽管提供的解决方案并没有直接解决我的问题,但它确实激发了我想出一个可行的解决方案。以下是我如何使用自定义错误处理程序处理编码和解码:

关键思想是在编码过程中将非 ASCII 字符编码为用方括号括起来的 UTF-8 十六进制表示形式。编码后,我在解码过程中使用正则表达式将十六进制编码值匹配并解码回原始字符。

这是更新的解决方案:

import codecs
import re


def utf8_hex_replace(exception):
    if isinstance(exception, UnicodeEncodeError):
        replacement = f"[{exception.object[exception.start].encode('UTF-8').hex(' ').upper()}]"
        next_pos = exception.start + 1
        return replacement, next_pos
    else:
        raise exception


def decode_utf8hexreplace(encoded_text):
    hex_pattern = re.compile(r'\[([0-9A-F ]+)]')
    return hex_pattern.sub(
        lambda match: bytes.fromhex(match.group(1)).decode('UTF-8'),
        encoded_text.decode('ASCII')
    )


codecs.register_error('utf8hexreplace', utf8_hex_replace)

if __name__ == '__main__':
    text = 'Hello, 世界'
    encoded = text.encode('ASCII', errors='utf8hexreplace')
    decoded = decode_utf8hexreplace(encoded)

    print(f'{encoded = }')
    print(f'{decoded = }')

通过这种方法,您可以将诸如

'Hello, 世界'
之类的字符串编码为 ASCII 字节字符串,其中包含由 UTF-8 十六进制值表示的非 ASCII 字符,然后通过替换十六进制编码值将其解码回原始字符串与相应的字符。

© www.soinside.com 2019 - 2024. All rights reserved.