本文介绍了在 Python 中运行交互式命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a script that I want to run from within Python (2.6.5) that follows the logic below:

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

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

The last prompt line contains text which I need to parse (filename.txt). The response provided doesn't matter (the program could actually exit here without providing one, as long as I can parse the line).

我的要求有点类似于在 Python 脚本中包装交互式命令行应用程序,但那里的响应似乎有点令人困惑,即使 OP 提到它不适合,我的仍然挂起他.

My requirements are somewhat similar to Wrapping an interactive command line application in a Python script, but the responses there seem a bit confusing, and mine still hangs even when the OP mentions that it doesn't for him.

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

Through looking around, I've come to the conclusion that subprocess is the best way of doing this, but I'm having a few issues. Here is my Popen line:

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

  • 当我在 stdout 上调用 read()readline() 时,提示是打印到屏幕上,它挂起.

    • When I call a read() or readline() on stdout, the prompt is printer to the screen and it hangs.

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

      If I call a write("password") for stdin, the prompt is written to the screen and it hangs. The text in write() is not written (I don't the cursor move the a new line).

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

      If I call p.communicate("password"), same behavior as write()

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

      I was looking for a few ideas here on the best way to input to stdin and possibly how to parse the last line in the output if your feeling generous, though I could probably figure that out eventually.

      推荐答案

      如果您正在与子进程产生的程序进行通信,您应该查看 在 Python 中对 subprocess.PIPE 进行非阻塞读取.我的应用程序遇到了类似的问题,发现使用 queues 是与子进程进行持续通信的最佳方式.

      If you are communicating with a program that subprocess spawns, you should check out A non-blocking read on a subprocess.PIPE in Python. I had a similar problem with my application and found using queues to be the best way to do ongoing communication with a subprocess.

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

      As for getting values from the user, you can always use the raw_input() builtin to get responses, and for passwords, try using the getpass module to get non-echoing passwords from your user. You can then parse those responses and write them to your subprocess' stdin.

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

      I ended up doing something akin to the following:

      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)
      

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

      Once you have the queues made and the threads started, you can loop through getting input from the user, getting errors and output from the process, and processing and displaying them to the user.

      这篇关于在 Python 中运行交互式命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-28 20:16
查看更多