【问题标题】:Python3 JSON encoding error "string argument without an encoding" when porting python 2.7x code to python 3.7x将 python 2.7x 代码移植到 python 3.7x 时,Python3 JSON 编码错误“没有编码的字符串参数”
【发布时间】:2020-05-03 06:48:31
【问题描述】:

我正在将 python 2.7x 代码移植到 python 3.7x。此代码尝试使用 TCP 套接字将一些数据发布到服务器。创建 JSON.dumps(data) 时出现编码错误。

 try:
         sei_nal_unit = create_sei_nal_unit(camera_config.SEI_UUID_CAMERA_SETTINGS, 
                        json.dumps(capture_settings) )
         #connection_filehandle.write(sei_nal_unit)
     except Exception as e:
          log.write("socket Thread TCP - exception in sending data [%s]" % (str(e)) ) 

   def encode_multibyte_value(value):
        """ encode values >= 255 as 0xff0xff..0xresidual """

        encoded = bytearray()

        while (value >= 255):
            encoded += bytearray(chr(255))
            value -= 255

        encoded += bytearray(chr(value))

        return encoded

    def escape_bytearray(input):
        """ escape 000 to 0030, 001 to 0031, 002 to 0032 and 003 to 0033 """
        output = bytearray()

        history1 = None
        history2 = None

        for b in input:
            if (history1==0) and (history2==0) and (b <= 3):
                output += chr(3)
                history1 = 3
                history2 = b
            else:
                history1 = history2
                history2 = b

            output += chr(b)    

        return output


       def create_sei_nal_unit(uuid, payload_string):
        """ create a 'user data unregistered' SEI nal unit in a bytearray """
        try:
            assert(bytearray == type(uuid))
            uuid_length = len(uuid)
            assert(16 == uuid_length)
            nal_unit_prefix = bytearray(b'\x00\x00\x00\x01')
            nal_unit_type = bytearray(chr(6))                   # 6 = SEI
            encoded_payload_type = encode_multibyte_value(5)    # 5 = 'user data unregistered'
            payload = bytearray(payload_string)
            encoded_payload_size = encode_multibyte_value(uuid_length + len(payload))
            escaped_payload = escape_bytearray(uuid + payload)
            trailing_bits = bytearray(b'\x80')
            sei_nal_unit = ( nal_unit_prefix
                       + nal_unit_type
                       + encoded_payload_type
                       + encoded_payload_size
                       + escaped_payload
                       + trailing_bits )
            return sei_nal_unit
        except Exception as e:
            print(str(e))

错误是

socket Thread TCP - an exception in sending data [string argument without an encoding]

JSON 文件是

capture_settings = [{"framerate": 30, "width": 1280, "height": 720, "bitrate": 17000000, "overlay": false, "gop_size": 30}]

我没有找到任何线索,我尝试了很多方法,但没有希望。谢谢你先进。

我已经尝试过你的方法,但它不起作用可能是我做错了什么。 python2的输出和python3的输出不同,服务器不排除数据。请查看 python2 代码及其输出以及 python3 代码及其输出

Python 2 代码

    import json

capture_settings= [{"framerate": 30, "width": 1280, "height": 720, "bitrate": 17000000, "overlay": False, "gop_size": 30}]

SEI_UUID_CAMERA_SETTINGS = bytearray(b'\x08\x94\xfc\xa2\x58\xce\x45\x02\x8f\x18\xc0\x8c\x68\xe5\x32\x35')
#print(len(SEI_UUID_CAMERA_SETTINGS))
#""" encode values >= 255 as 0xff0xff..0xresidual """
def encode_multibyte_value(value):
    """ encode values >= 255 as 0xff0xff..0xresidual """

    encoded = bytearray()

    while (value >= 255):
        encoded += bytearray(chr(255))
        value -= 255

    encoded += bytearray(chr(value))

    return encoded

def escape_bytearray(input):
    """ escape 000 to 0030, 001 to 0031, 002 to 0032 and 003 to 0033 """
    output = bytearray()

    history1 = None
    history2 = None

    for b in input:
        if (history1==0) and (history2==0) and (b <= 3):
            output += chr(3)
            history1 = 3
            history2 = b
        else:
            history1 = history2
            history2 = b

        output += chr(b)    

    return output


def create_sei_nal_unit(uuid, payload_string):
    """ create a 'user data unregistered' SEI nal unit in a bytearray """

    assert(bytearray == type(uuid))
    print(uuid)

    uuid_length = len(uuid)
    assert(16 == uuid_length)   

    nal_unit_prefix = bytearray(b'\x00\x00\x00\x01')
    nal_unit_type = bytearray(chr(6))                   # 6 = SEI

    encoded_payload_type = encode_multibyte_value(5)    # 5 = 'user data unregistered'

    payload = bytearray(payload_string)

    encoded_payload_size = encode_multibyte_value(uuid_length + len(payload))
    print(uuid + payload)
    escaped_payload = escape_bytearray(uuid + payload)


    trailing_bits = bytearray(b'\x80')

    sei_nal_unit = ( nal_unit_prefix
                   + nal_unit_type
                   + encoded_payload_type
                   + encoded_payload_size
                   + escaped_payload
                   + trailing_bits )

    return sei_nal_unit

sei_nal_unit = create_sei_nal_unit(SEI_UUID_CAMERA_SETTINGS, json.dumps(capture_settings))
print(sei_nal_unit)

它的输出是

x����X�E���h�25[{"overlay": false, "gop_size": 30, "framerate": 30,“高度”:720,“宽度”:1280,“比特率”:17000000}]。

python3代码

 import json


capture_settings= [{"framerate": 30, "width": 1280, "height": 720, "bitrate": 17000000, "overlay": False, "gop_size": 30}]

SEI_UUID_CAMERA_SETTINGS = b'\x08\x94\xfc\xa2\x58\xce\x45\x02\x8f\x18\xc0\x8c\x68\xe5\x32\x35'
#print(len(SEI_UUID_CAMERA_SETTINGS))
#""" encode values >= 255 as 0xff0xff..0xresidual """
def encode_multibyte_value(value):
    """ encode values >= 255 as 0xff0xff..0xresidual """

    encoded = bytes()

    while (value >= 255):
        encoded += bytes(chr(255).encode('utf-8'))
        value -= 255

    encoded += bytes(chr(value).encode('utf-8'))

    return encoded

def escape_bytearray(input):
    """ escape 000 to 0030, 001 to 0031, 002 to 0032 and 003 to 0033 """
    output = bytes()

    history1 = None
    history2 = None

    for b in input:
        if (history1==0) and (history2==0) and (b <= 3):
            output += b'\x03'
            history1 = 3
            history2 = b
        else:
            history1 = history2
            history2 = b

        output += chr(b).encode('utf-8')    

    return output


def create_sei_nal_unit(uuid, payload_string):
    """ create a 'user data unregistered' SEI nal unit in a bytearray """

    assert(bytes == type(uuid))

    uuid_length = len(uuid)
    assert(16 == uuid_length)   

    nal_unit_prefix = b'\x00\x00\x00\x01'
    nal_unit_type = b'\x06'                  # 6 = SEI
    encoded_payload_type = encode_multibyte_value(5)    # 5 = 'user data unregistered'

    payload = bytes(payload_string)

    encoded_payload_size = encode_multibyte_value(uuid_length + len(payload))
    escaped_payload = escape_bytearray(uuid + payload)


    trailing_bits = b'\x80'

    sei_nal_unit = ( nal_unit_prefix
                   + nal_unit_type
                   + encoded_payload_type
                   + encoded_payload_size
                   + escaped_payload
                   + trailing_bits )

    return sei_nal_unit

sei_nal_unit = create_sei_nal_unit(SEI_UUID_CAMERA_SETTINGS, json.dumps(capture_settings).encode('utf-8'))
print(sei_nal_unit)

它的输出

b'\x00\x00\x00\x01\x06\x05x\x08\xc2\x94\xc3\xbc\xc2\xa2X\xc3\x8eE\x02\xc2\x8f\x18\xc3\x80\xc2\ x8ch\xc3\xa525[{“帧率”: 30、“宽度”:1280、“高度”:720、“比特率”:17000000、“叠加”: 假,“gop_size”:30}]\x80'

在 python2 中,服务器排除数据,但在 python3 中,它不排除 dat。请让我python3代码中的错误是什么。谢谢。

【问题讨论】:

    标签: json python-3.x python-2.7 http http-post


    【解决方案1】:

    json.dumps() 调用返回一个字符串。在通过 TCP 套接字发送之前,您必须将其编码为 bytes。最简单的就是使用:

    json.dumps(capture_settings).encode('ascii')
    

    默认情况下,json.dumps() 将确保字符串中的所有非 ascii 字符都完全转义,因此您可以安全地使用 .encode('ascii') 将字符串转换为 bytes

    (有一个ensure_ascii 参数可以设置False 用于您知道服务器可以处理其他编码(例如utf-8)但这里只使用ascii 就足够的情况。)

    你也不能做bytearray(chr(6)),因为bytearray() 需要一个bytes 参数并且chr() 返回一个字符串。 bytearray(b'\06') 可以工作,但所有代码可能会更简单,直接使用bytes 值而不是bytearray

    bytearray 是一个可变字节序列,除非您需要可变性,请尝试直接使用bytes

    如果您将参数重命名为payload_bytes(因为现在您正在传递字节),那么这可能有效(您可以连接bytesbytearray):

            nal_unit_prefix = b'\x00\x00\x00\x01'
            nal_unit_type = b'\x06'                  # 6 = SEI
            encoded_payload_type = encode_multibyte_value(5)    # 5 = 'user data unregistered'
    
            encoded_payload_size = encode_multibyte_value(uuid_length + len(payload))
            escaped_payload = escape_bytearray(uuid + payload_bytes)
            trailing_bits = b'\x80'
            sei_nal_unit = ( nal_unit_prefix
                       + nal_unit_type
                       + encoded_payload_type
                       + encoded_payload_size
                       + escaped_payload
                       + trailing_bits )
    

    【讨论】:

    • 感谢@Duncan 先生的回复。我已经按照您的建议尝试了您的方法,但仍然遇到相同的错误。我不明白为什么。我也使用了json.dumps(capture_setting).encode('utf-8'),但同样的错误虽然在 python2 中它在没有任何编码的情况下完美地工作
    • 是的,您有另一个字符串隐藏为chr(6)。答案已更新。
    • 谢谢@Duncan 先生的课程,我明白了。我会试一试,然后告诉你。
    • 我遇到了一些错误,请帮我找到我编辑问题的错误,其中我在输出中包含了 python2 和 python3 代码。
    猜你喜欢
    • 2015-09-18
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多