将带有args的命令传递给subprocess.Popen

时间:2018-10-26 19:29:59

标签: python python-3.x

当我尝试将批处理文件(不需要任何参数)传递给函数时,以下脚本可以正常工作。

script_as_var = os.path.join(os.environ['SOME_VAR'], 'bin/stop.bat')
jboss = os.path.join(os.environ['JBOSS_HOME'], 'bin/jboss-cli.bat')

def status(some_arg, cmd, more_arg):
    print('CMD: ' + cmd)
    ps = subprocess.Popen(cmd, stdout=subprocess.PIPE)
    output = ps.communicate()[0]
    ...
    ...

status(10, script_as_var, 'last_arg')   # Works fine

但是,当我尝试将以下命令传递给该函数时,它将失败。

status(15, '[jboss,'"'-c'"','"'--commands="'"read-attribute server-state"'"'"']',
       'some_arg')

输出:

CMD: [jboss,'-c','--commands='"read-attribute server-state"'']
...
FileNotFoundError: [WinError 2] The system cannot find the file specified

下面的命令在我没有创建函数时可以正常工作。

ps = subprocess.Popen([jboss,'-c','--commands='"read-attribute server-state"''],
                      stdout=subprocess.PIPE)

print命令的输出中可以注意到,我成功地以某种方式(通过使用凌乱的单引号和双引号组合)传递了我可以在不使用此功能时运行的确切命令已创建,但似乎jboss变量扩展还需要一些工作。

有什么主意我可以解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

subprocess.Popen构造函数将接受字符串或诸如list之类的序列作为其名为 args 的第一个参数。您的代码似乎正在尝试同时使用这两种方法……这是正确执行此操作的方法。如您所见,它还在根据需要扩展jboss变量。

import os
os.environ['SOME_VAR'] = 'some_var'          # For testing
os.environ['JBOSS_HOME'] = 'jboss_home_var'  # For testing

script_as_var = os.path.join(os.environ['SOME_VAR'], 'bin/stop.bat')
jboss = os.path.join(os.environ['JBOSS_HOME'], 'bin/jboss-cli.bat')

def status(some_arg, cmd, more_arg):
    print('CMD: ' + repr(cmd))
#    ps = subprocess.Popen(cmd, stdout=subprocess.PIPE)
#    output = ps.communicate()[0]
#    ...
#    ...

status(10, script_as_var, 'last_arg')
status(15, [jboss, '-c', '--commands="read-attribute server-state"'], 'some_arg')

输出:

CMD: 'some_var\\bin/stop.bat'
CMD: ['jboss_home_var\\bin/jboss-cli.bat', '-c', '--commands="read-attribute server-state"']

答案 1 :(得分:1)

您正在传递str的命令。请注意,您的工作示例中有一个list。您只需要除去所有多余的报价并传递列表即可。

>>> def foo(a, b, c):
  print(b) 

>>> jboss = 42

>>> foo(15,'[jboss,'"'-c'"','"'--commands="'"read-attribute server-state"'"'"']','some_arg')
[jboss,'-c','--commands="read-attribute server-state"']

>>> foo(15,[jboss,'-c','--commands="read-attribute server-state"'],'some_arg')
[42, '-c', '--commands="read-attribute server-state"']