【问题标题】:Calling bash script as Python subprocess - Bash falls into endless loop getting bad input调用 bash 脚本作为 Python 子进程 - Bash 陷入无限循环,输入错误
【发布时间】:2017-04-29 01:12:52
【问题描述】:

我正在使用 Python 2.7 和 Glade 3.15 创建一个 GUI,允许单击按钮执行由我的工作团队维护的各种现有 bash/cshell 脚本。我对 Python 还很陌生,但已经设法让基本的应用程序结构正常运行。但是,我正在调用的某些 bash 脚本将逐步执行多个用户提示并接受输入以确定最终行为。我遇到的问题是,当我将 bash 脚本调用为 python 子进程时,bash 脚本似乎一遍又一遍地接受空输入,从而导致提示无休止地循环。

例如: 一个bash脚本提示:

"Please enter your 4 digit document number:"
  ** accept user input in terminal **
"You entered ----, is that correct?
       1.) Yes
       2.) No " 

当从 python 调用时,终端将按提示,发送一个空响应。由于 bash 脚本循环直到收到肯定的响应,结果是终端无休止地打印:

"You entered ----, is that correct?
         1.) Yes
         2.) No "

我已广泛尝试在这里和其他地方寻找有关此问题的答案,但尚未找到/开发解决方案。

我的基本python,相对于这个问题,如下(虽然我尝试了各种各样不同的方法)

import subprocess
from subprocess import Popen,PIPE
...
# Definition for subprocess calls
  def subprocess_cmd(self, command):
     process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)   
     process.wait()
     (output, err) = process.communicate()
     print output
...

# Script-Call Button
  def on_btnScript_clicked(self, object, data=None):
    self.subprocess_cmd("scriptname_is_here")

我只想从我的 python button_click 事件中调用一个子进程,该事件在终端中启动 bash 脚本,并等待键盘终端输入以遍历提示,就像它直接从终端运行一样。抱歉这么久 - 想要彻底和明确。提前感谢您的帮助。

*****更新****

如果我使用 .wait() 方法从另一个独立的 python 文件调用子进程,则交互将按需要进行。但是,当我由于 GUI button_click 事件调用子进程时,使用相同的参数和方法,就会发生循环异常。我认为这与我在 mainDialog 类中定义的按钮单击事件和 subprocess_cmd 'function' 有关,但我不知道如何在保持与 GUI 的连接的同时将它们分开。

这是我的代码的更多上下文

#!/usr/bin/python

# Library Imports
from gi.repository import Gtk
from os import system
import subprocess
from subprocess import Popen,PIPE
import time
try:
  import math
except:
   print "Math Library Missing"
   sys.exit(1)

class mainDialog:

# Build the 'form load' parameters
  def __init__(self):
    self.gladefile = "test.glade"
    self.builder = Gtk.Builder()
    self.builder.add_from_file(self.gladefile)
    self.builder.connect_signals(self)
    self.winMain = self.builder.get_object("winMain")
    self.winCptArg = self.builder.get_object("winCptArg")
    self.winMsbHelp = self.builder.get_object("winMsbHelp")
    self.winCptHelp = self.builder.get_object("winCptHelp")
    self.winAiHelp = self.builder.get_object("winAiHelp")
    self.winMain.move(2625, 400)
    self.winMain.show()

# Definition for subprocess calls
  def subprocess_cmd(self, command):
     process = subprocess.Popen(command)   
     process.wait()
...

# Script-Call Button
  def on_btnScript_clicked(self, object, data=None):
    self.subprocess_cmd("scriptname_is_here")

if __name__ == "__main__":
  main = mainDialog()
  Gtk.main()

【问题讨论】:

  • stdin=subprocess.PIPE 表示子进程应该从管道而不是终端获取输入。
  • 您已将Popen 呼叫配置为stdin=Subprocess.PIPE。这将不允许接受任何输入。
  • 谢谢。这是有道理的,我感谢你澄清。你能解释一下我应该设置什么标准输入来接收终端输入吗?我试过 stdin=None,它不起作用,也没有定义 stdin。谢谢

标签: python linux bash python-2.7 shell


【解决方案1】:

只需使用os.system:

from os import system
...
# Definition for subprocess calls
def subprocess_cmd(self, command):
    process = system(str(command))
...
# Script-Call Button
def on_btnScript_clicked(self, object, data=None):
    self.os.system("echo scriptname_is_here")

语法是os.system("executable option parameter")
例如,

os.system("ls -al /home")

【讨论】:

  • 感谢您的回复。这似乎实现了我正在寻找的基本功能,但我不知道如何通过这个调用传递参数——有什么建议吗?
  • 我添加了你所要求的语法
【解决方案2】:

好吧,如果有人有兴趣,为了实现我的意图,我只是将 stdin 和 stdout 单独放置,并将 .wait() 方法应用于子进程定义——但这仅在从独立 python 脚本调用时才有效;连接到 GUI 按钮单击事件时,我无法保留功能。

 def subprocess_cmd(self, command):
     process = subprocess.Popen(command).wait() 
...

 def on_btnScript_clicked(self, object, data=None):
    self.subprocess_cmd("filepath/scriptname_is_here")

stdin和stdout可以保持默认,可以实现标准的终端交互,只要子进程定义附加wait()方法即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 2014-08-25
    相关资源
    最近更新 更多