【问题标题】:How to convert socket data to json object or to Dictionary with Python 3如何使用 Python 3 将套接字数据转换为 json 对象或字典
【发布时间】:2019-01-13 17:31:53
【问题描述】:

所以我正在尝试将数据从套接字转换为 json 对象。 下面是我从套接字服务器获取数据的python代码。

import socket

HOST = "myHOST"
PORT = myPORT
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((myHOST, myPORT))
    s.sendall(b" ")
    buffer_size = 4096
    print("Received: ")
    while True:
        data = s.recv(buffer_size)
        print(repr(data))
s.close()

我正在获取这些数据作为输出:

Received: 
b'2018-08-06T17:35:45.0612|power|ON|mode|MANUAL|execution|READY|Xact|215.13|Yact|331.34|Zact|22.16|Xcom|0.00|Ycom|0.00|Zcom|0.00|path_feedrate|0.00|line|0|Block|0|program|Plate 1_imported_dxf.ORD\n'
b'2018-08-06T17:35:45.0612|comms|NORMAL||||\n2018-08-06T17:35:45.0612|Sspeed|0.00\n'

现在我想将它转换为格式化的 json 对象,以便以后可以在我的 html 中使用 javascript 来使用它。我尝试通过以下方式在我的 while 循环中创建 json 对象:

import socket
import json

HOST = "myHOST"
PORT = myPORT
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((myHOST, myPORT))
    s.sendall(b" ")
    buffer_size = 4096
    print("Received: ")
    while True:
        data = s.recv(buffer_size)
        print(repr(data))

        json_obj = json.loads(data)
        print(type(json_obj))
        print(json_obj.get("power").get("mode"))
s.close()

但我不能让它工作。我也尝试使用 json.dumps 但没有成功。 请帮助伙计们!我也尝试制作字典,但没有成功,出现错误:ValueError: too many values to unpack (expected 2)。 以下是我的字典尝试的 sn-p:

while True:
    data = s.recv(buffer_size).decode("utf-8")
    print(data)
    d = {}
    for pair in data.replace(' ', '').split(', '):
        k, v = pair.split('|')
        d[k] = int(v)
    print(d)

我希望答案有键值对。

【问题讨论】:

  • 你得到的错误是什么?服务器是什么样的?
  • 您错误地使用了套接字。 recv 得到 1 到 4096 个字节,而不是消息。你为什么不使用http?
  • 这不是我的recv的问题。因为我正在获取实时数据,但是从那些杂乱的数据创建 json 对象时出现问题。当我尝试创建它时出现错误:json.decoder.JSONDecodeError: Extra data:..... 我无法修复
  • 您收到的数据不是 JSON。为什么您认为 JSON 解析器会理解它?您必须首先:确保从套接字流中读取了完整的记录,第二:将其转换为 JSON,第三:解析。或者直接将其解析为您需要的内容并跳过 JSON 步骤。
  • 谢谢Shawn,好的,但是我怎样才能将它解析为跳过json步骤的字典?你能帮帮我吗?

标签: python json sockets telnet


【解决方案1】:
import socket

HOST = "myHOST"
PORT = myPORT
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((myHOST, myPORT))
    buffer_size = 2048
    print("Received: ")
    while True:
        devData = s.recv(buffer_size).decode("utf-8").split("|")
        timeStamp = devData.pop(0)
        devDict = dict(zip(*([iter(devData)]*2)))
        print(devDict)
s.close()

这是我得到的结果:

Received: 
{'power': 'ON', 'mode': 'MANUAL', 'execution': 'READY', 'Xact': '1113.21', 'Yact': '162.60', 'Zact': '0.00', 'Xcom': '0.00', 'Ycom': '0.00', 'Zcom': '0.00', 'path_feedrate': '0.00', 'line': '0', 'Block': '0', 'program': '37255 S1 D - .75 JET_imported_dwg.ORD\n'}
{'comms': 'NORMAL', '': '\n2018-08-07T20:40:05.0432', 'Sspeed': '0.00\n'}
{'program': '37255 S1 D - .75 JET_imported_CNC.ORD\n'}
{'power': 'ON', 'mode': 'MANUAL', 'execution': 'READY', 'Xact': '1113.21', 'Yact': '162.60', 'Zact': '0.00', 'Xcom': '0.00', 'Ycom': '0.00', 'Zcom': '0.00', 'path_feedrate': '0.00', 'line': '0', 'Block': '0', 'program': '37255 S1 D - .75 JET_imported_CNC.ORD\n'}
{'comms': 'NORMAL', '': '\n2018-08-07T20:43:57.0375', 'Sspeed': '0.00\n'}

【讨论】:

    【解决方案2】:

    在这里猜测一下,因为您没有准确定义您希望看到的输出,但它似乎很清楚,可以试一试。首先,第一列似乎有一个隐含的键(我称之为“时间戳”)。然后,似乎键和值交替出现。

    假设是这种情况,并且您将确保在输入中只提供完整的行(* 见下文),以下应该可以工作。为简洁起见,您可以在这里组合很多东西。我将把它全部用于教育:

    import json
    
    input_data = [
        b'2018-08-06T17:35:45.0612|power|ON|mode|MANUAL|execution|READY|Xact|215.13|Yact|331.34|Zact|22.16|Xcom|0.00|Ycom|0.00|Zcom|0.00|path_feedrate|0.00|line|0|Block|0|program|Plate 1_imported_dxf.ORD\n',
        b'2018-08-06T17:35:45.0612|comms|NORMAL||||\n2018-08-06T17:35:45.0612|Sspeed|0.00\n'
    ]
    
    for x in input_data:
    
        # Sometimes the input data has multiple lines, so split into lines
        for line in x.decode().splitlines():
    
            # Drop white space (if necessary; splitlines() already drops newlines)
            data = line.strip()
            print("LINE:", data)
    
            # Split by vertical bars to produce "atoms"
            atoms = data.split('|')
            print("ATOMS:", atoms)
    
            # Supply implicit timestamp key plus odd-numbered atoms
            keys = ['timestamp'] + list(atoms[1::2])
    
            # Values from even-numbered atoms
            values = list(atoms[::2])    
    
            print("KEYS:", keys)
            print("VALUES:", values)
    
            # What if they aren't one for one?
            assert len(keys) == len(values)
    
            # Drop key and value if key is null (reasonable that value might be null?)
            zipped = [(k, v) for k, v in zip(keys, values) if k]
            print("ZIPPED:", zipped)
    
            d = dict(zipped)
            print("DICT:", d)
    
            print("JSON:", json.dumps(d))
            print()
    


    重要提示

    recv 不保证将整行发送给您即使对等方将它们作为完整行发送。当这很重要时(如这里),您需要在 recv 和您的应用程序逻辑之间放置一个“缓冲”层,它会继续接收字节,直到找到行尾。

    【讨论】:

    • 谢谢@Gil。我也修好了,后来发现还是比较容易的。
    猜你喜欢
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    相关资源
    最近更新 更多