Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在将stdin、stdout和stderr设置为subprocess.PIPE的情况下调用subprocess.Popen会更改终端的行为_Python_Subprocess_Pipe_Popen - Fatal编程技术网

Python 在将stdin、stdout和stderr设置为subprocess.PIPE的情况下调用subprocess.Popen会更改终端的行为

Python 在将stdin、stdout和stderr设置为subprocess.PIPE的情况下调用subprocess.Popen会更改终端的行为,python,subprocess,pipe,popen,Python,Subprocess,Pipe,Popen,我最近开发了一个Python脚本,以利用一个工具通过JMX从JVM检索指标。父进程p1使用以下代码启动另一个进程p2 p2启动并运行后,p1将进入一个非常长的循环,在该循环中执行以下三项操作: 睡眠10秒; 通过调用p2.stdin.write向p2发送查询; 通过调用p2.stdout.readline读取结果。 问题: 我的脚本按预期工作,直到退出。如果我按Ctrl+C停止p1并返回终端,一切正常。如果我等到p1完成长循环并退出,终端工作正常,只是我输入的所有字符不再可见。例如,如果我输入“

我最近开发了一个Python脚本,以利用一个工具通过JMX从JVM检索指标。父进程p1使用以下代码启动另一个进程p2

p2启动并运行后,p1将进入一个非常长的循环,在该循环中执行以下三项操作:

睡眠10秒; 通过调用p2.stdin.write向p2发送查询; 通过调用p2.stdout.readline读取结果。 问题:

我的脚本按预期工作,直到退出。如果我按Ctrl+C停止p1并返回终端,一切正常。如果我等到p1完成长循环并退出,终端工作正常,只是我输入的所有字符不再可见。例如,如果我输入“ls”,我在屏幕上什么也看不到。但是当我点击Return时,我仍然可以像往常一样看到列出的文件和子目录。我的问题是,幕后发生了什么? 如果我删除stderr=subprocess.PIPE,jmxterm打印到stderr的帮助消息将转到终端。因为它们弄乱了我的脚本的输出,我试图改变

['java', '-jar', '/path/to/jmxterm-1.0-alpha-4-uber.jar', '-l', url,
         '-u', username, '-p', password]

但一切都没有改变,帮助信息仍然发送到终端。然后,我将stderr=subprocess.PIPE添加回我的脚本,并启动一个守护进程线程从stderr读取并丢弃它读取的内容。令我惊讶的是,守护进程线程没有从stderr读取任何内容。我完全迷路了。如果你有线索,请帮我一把

代码粘贴在下面供您参考:

from Queue import Queue

class JmxD(Detector):

    def __init__(self, myId, jmxUrl, username, password):
        super(JmxD, self).__init__(myId)

        self.__jmxUrl = jmxUrl
        self.__username = username
        self.__password = password

        # Start JMX terminal
        self.__jmxTerm = subprocess.Popen(
            ['java', '-jar', jmxTermPath,
             '-l', jmxUrl, '-u', username, '-p', password],
            stdin = subprocess.PIPE,
            stdout = subprocess.PIPE,
            stderr = subprocess.PIPE)

        # Start two daemon threads to read from JMX terminal's stdout & stderr
        def _stream2Queue(out, queue):
            for line in iter(out.readline, ''):
                line = line.strip()
                if line:
                    queue.put(line)
            out.close()

        def _stream2Null(out):
            for line in iter(out.readline, ''):
                #print 'A line read from stderr: %s' % line.strip()
                pass
            out.close()

        self.__queue = Queue()
        self.__reader = Thread(target=_stream2Queue,
                               args=(self.__jmxTerm.stdout, self.__queue))
        self.__reader.setDaemon(True) # This thread dies with the program
        self.__reader.start()

        self.__discarder = Thread(target=_stream2Null,
                                  args=(self.__jmxTerm.stderr))
        self.__discarder.setDaemon(True) # This thread dies with the program
        self.__discarder.start()

我的猜测是,当终端正确关闭时,java进程正在干扰终端。如果你只是想让你的终端恢复正常,那么只要运行reset,你就可以开始了。派克勒:谢谢你的技巧。除非你正在阅读,否则不要使用stderr=PIPE。在循环结束后调用p2.communicate关闭流并等待p2退出。塞巴斯蒂安:非常感谢你的回复。我刚刚遇到了另一个问题。如果你有线索的话,请你看一下并告诉我好吗?谢谢。顺便说一下,添加2>/dev/null不起作用的原因是:当您在终端中的命令末尾键入2>/dev/null时,shell会捕获它并将其解释为一个命令,用于设置机器以丢弃进程打印到标准错误的任何内容。在去掉像这样的特殊shell指令后,shell会将剩下的部分作为参数列表传递给C版本的Popen。当使用Python的Popen时,您没有一个shell来解释这些特殊的shell指令,所以它们什么都不做。仅供参考,`Popen有一个shell=True选项。
['java', '-jar', '/path/to/jmxterm-1.0-alpha-4-uber.jar', '-l', url,
         '-u', username, '-p', password, '2>/dev/null']
from Queue import Queue

class JmxD(Detector):

    def __init__(self, myId, jmxUrl, username, password):
        super(JmxD, self).__init__(myId)

        self.__jmxUrl = jmxUrl
        self.__username = username
        self.__password = password

        # Start JMX terminal
        self.__jmxTerm = subprocess.Popen(
            ['java', '-jar', jmxTermPath,
             '-l', jmxUrl, '-u', username, '-p', password],
            stdin = subprocess.PIPE,
            stdout = subprocess.PIPE,
            stderr = subprocess.PIPE)

        # Start two daemon threads to read from JMX terminal's stdout & stderr
        def _stream2Queue(out, queue):
            for line in iter(out.readline, ''):
                line = line.strip()
                if line:
                    queue.put(line)
            out.close()

        def _stream2Null(out):
            for line in iter(out.readline, ''):
                #print 'A line read from stderr: %s' % line.strip()
                pass
            out.close()

        self.__queue = Queue()
        self.__reader = Thread(target=_stream2Queue,
                               args=(self.__jmxTerm.stdout, self.__queue))
        self.__reader.setDaemon(True) # This thread dies with the program
        self.__reader.start()

        self.__discarder = Thread(target=_stream2Null,
                                  args=(self.__jmxTerm.stderr))
        self.__discarder.setDaemon(True) # This thread dies with the program
        self.__discarder.start()