python - 在 Python 中运行交互式命令

标签 python subprocess stdout stdin interactive

我想在 Python (2.6.5) 中运行一个脚本,该脚本遵循以下逻辑:

  • 提示用户输入密码。它看起来像(“输入密码:”)(*注意:输入不会回显到屏幕)
  • 输出无关信息
  • 提示用户回复(“Blah Blah filename.txt blah blah (Y/N)?:”)

最后一行包含我需要解析的文本(filename.txt)。提供的响应无关紧要(只要我可以解析该行,程序实际上可以在不提供响应的情况下退出这里)。

我的要求有点类似于 Wrapping an interactive command line application in a Python script ,但是那里的响应似乎有点令人困惑,即使 OP 提到它不适合他,我的仍然挂起。

通过环顾四周,我得出的结论是 subprocess 是执行此操作的最佳方式,但我遇到了一些问题。这是我的 Popen 行:

p = subprocess.Popen("cmd", shell=True, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
  • 当我在 stdout 上调用 read()readline() 时,提示是打印到屏幕上,它挂起。

  • 如果我为 stdin 调用 write("password\n"),提示将写入屏幕并挂起。 write() 中的文本没有写入(我没有将光标移到新行)。

  • 如果我调用 p.communicate("password\n"),与 write() 的行为相同

我在这里寻找一些关于输入 stdin 的最佳方式的想法,以及如果您觉得慷慨的话,可能如何解析输出中的最后一行,尽管我最终可能会弄清楚.

最佳答案

如果您正在与子进程生成的程序进行通信,您应该查看 A non-blocking read on a subprocess.PIPE in Python 。我的应用程序遇到了类似的问题,发现使用 queues 是与子进程进行持续通信的最佳方式。

至于从用户那里获取值,你总是可以使用 raw_input() 内置函数来获取响应,对于密码,尝试使用 getpass模块从您的用户那里获取非回显密码。然后,您可以解析这些响应并将它们写入您的子进程的标准输入。

我最终做了类似于以下的事情:

import sys
import subprocess
from threading import Thread

try:
    from Queue import Queue, Empty
except ImportError:
    from queue import Queue, Empty  # Python 3.x


def enqueue_output(out, queue):
    for line in iter(out.readline, b''):
        queue.put(line)
    out.close()


def getOutput(outQueue):
    outStr = ''
    try:
        while True: # Adds output from the Queue until it is empty
            outStr+=outQueue.get_nowait()

    except Empty:
        return outStr

p = subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, universal_newlines=True)

outQueue = Queue()
errQueue = Queue()

outThread = Thread(target=enqueue_output, args=(p.stdout, outQueue))
errThread = Thread(target=enqueue_output, args=(p.stderr, errQueue))

outThread.daemon = True
errThread.daemon = True

outThread.start()
errThread.start()

try:
    someInput = raw_input("Input: ")
except NameError:
    someInput = input("Input: ")

p.stdin.write(someInput)
errors = getOutput(errQueue)
output = getOutput(outQueue)

一旦创建了队列并启动了线程,就可以循环获取用户的输入、进程的错误和输出,以及处理并将它们显示给用户。

关于python - 在 Python 中运行交互式命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11457931/

相关文章:

python - 如何使用列表(而不是 Pandas )仅根据月份和日期对日期项进行排序?

python - groupby 包含列表的列

python - 我什么时候应该使用 subprocess.Popen 而不是 os.popen?

makefile - 如何解开并行 make -j 编译器消息?

python - 如何在numpy数组中拆分字符串?

python - 将文件元素读入邻接表

python - 接收 SIGUSR2/SIGINT 时如何在 python 中获取子进程的标准输出

python - 在 python 中运行 shell 脚本

linux - 这个 ksh 代码是如何工作的?

python - 获取已打印python的文本内容