python - 为什么 `stdin.read()` 不读取整个缓冲区?

标签 python json

我有以下代码:

def get_input(self):
    """
    Reads command from stdin, returns its JSON form
    """
    json_string = sys.stdin.read()
    print("json string is: "+json_string)
    json_data =json.loads(json_string)
    return json_data

def accept_commands(self):
    while True:
        json_data = self.get_input()
        command = self.command_analyzer.is_command(json_data) # Check wether the command exists. Return it if it does
        #The command exists
        if command is not None:
            #The addon is not currently active
            if analyzer.intent(json_data) not in self.active_addons:
                self.activate_addon(command,json_data)

            #The addon is active and so we need to send the data to the subprocess
            else:
                self.communicate_with_addon(command,json_data,json_string)

它读取从另一个进程发送给它的 json 字符串。 json 是从 stdin 读取的。 由于某种原因,我得到以下输出:

json string is: <Some json here>
json string is: 
Traceback (most recent call last):
  File "/Users/Matan/Documents/workspace/ProjectSH/addonmanager/addon_manager.py", line 63, in <module>
    manager.accept_commands()
  File "/Users/Matan/Documents/workspace/ProjectSH/addonmanager/addon_manager.py", line 49, in accept_commands
    json_data = self.get_input()
  File "/Users/Matan/Documents/workspace/ProjectSH/addonmanager/addon_manager.py", line 42, in get_input
    json_data =json.loads(json_string)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 365, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 383, in raw_decode
    raise ValueError("No JSON object could be decoded")

json 是从以下位置发送的:

class MessageReceiver:

    def __init__(self):
        '''
        Connect to the AMQP broker and starts listening for messages.
        Creates the a Popen object to pass command info to the addon_manager script (which
        is in charge of managing scripts)
        '''
        addon_manager_path = configuration.addon_manager_path()
        addon_manager_path = os.path.join(addon_manager_path,'addon_manager.py')
        execute = "python " + addon_manager_path
        self.addon_manager = subprocess.Popen(execute, stdin=subprocess.PIPE, shell=True)


        self.component_name= configuration.get_attribute("name")

        if len(sys.argv)>1:
            host_ip = sys.argv[1]
        else:
            host_ip = 'localhost'

        #Start a connection to the AMQP server
        self.connection = pika.BlockingConnection(pika.ConnectionParameters(host=host_ip))

        #Create a channel to the server
        self.channel = self.connection.channel()

        self.channel.queue_declare(queue="kitchen")

        #callback method to be called when data is received
        #It sends the data that is received by the client to the addon_manager
        def data_received(ch, method, properties, body):
            ##TODO: Might want to add some checks. Is body a JSON? etc.
            print("writing data to addon_manager")
            self.addon_manager.communicate(body)


        self.channel.basic_consume(data_received,queue='kitchen',no_ack=True)


        self.channel.start_consuming()

这里出了什么问题?

最佳答案

默认情况下,stdin.read() 会阻塞,直到读取整个缓冲区。如果您只能解码一个 JSON 对象,那么这就是在 stdin 被另一进程关闭之前发送的所有内容。

如果您需要流式传输多个 JSON block ,您应该

a) 不关闭写入过程中的流,并且 b) 不要在 Python 中进行阻塞读取。

改为分块或按行读取;请参阅Loading and parsing a JSON file with multiple JSON objects in PythonHow do I use the 'json' module to read in one JSON object at a time?了解读取行分隔或多行的 JSON 对象的技术。

您可以调整其中之一来生成生成器函数;您可以对其进行循环以一次生成一个 JSON 对象,并在中间阻塞以等待下一个 JSON 对象:

def get_input(self):
    for line in sys.stdin:
        yield json.loads(line)

def accept_commands(self):
    for json_data in self.get_input():
        # do something with `json_data`

您正在使用Popen.communicate()写入管道。这会在写入后关闭管道,然后等待进程终止。

如果您希望管道保持打开状态,请不要使用 Popen.communicate 而是直接写入 Popen.stdin pipe .

关于python - 为什么 `stdin.read()` 不读取整个缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25483684/

相关文章:

python - 在 Python 2.7.5 中比较字符串和 unicode

python - 用字典键匹配 Pandas 子字符串并用字典值替换

java - Gson在反序列化对象时忽略null

ruby-on-rails - rails : Is it neccessary to wrap my POST response in a respond_to block?

Android解析org.json.JSONObject对象没有 "getFloat"方法。我该怎么办?

javascript - 如何比较 JavaScript 中的数组?

python - 使 ModelForm 与 Django 中的中间模型的多对多关系工作的步骤是什么?

python - 以下代码中使用什么公式来计算 ys?

python - 交互模式下 sys.stdout 的输出

ios - 如何在uitableview中搜索并显示youtube视频?