2013-11-22 4 views
6

У меня есть сценарий, который вызывает другой скрипт python подпроцессом. Модуль Popen. Но так как у меня есть аргументы, хранящиеся в переменной (ы)Передача переменных в Subprocess.Popen

servers[server]['address'] 
servers[server]['port'] 
servers[server]['pass'] 

Я не могу выполнить команду

p = subprocess.Popen(["python mytool.py -a ", servers[server]['address'], "-x", servers[server]['port'], "-p", servers[server]['pass'], "some additional command"], shell=True, stdout=subprocess.PIPE) 

Обход:

Я получил его на работу, расчесывая @wilberforce & @ ответ ciphor но небольшая модификация

command = "python mytool.py -a %s -x %s -p %s some additional command" % (servers[server]['address'], servers[server]['port'], servers[server]['pass']) 
p = subprocess.Popen(command , shell=True, stdout=subprocess.PIPE) 

Он перестает работать, если я добавил несколько переменных в двойные кавычки, он может принимать значения с максимальными «2» переменными и ломаться. Я добавил больше.

Спасибо всем, кто ответил!

+1

Используйте переменные для построения строки, которая является командой, или передайте их в виде списка аргументов. – beroe

ответ

5

Капля shell=True. The arguments to Popen() are treated differently on Unix if shell=True:

import sys 
from subprocess import Popen, PIPE 

# populate list of arguments 
args = ["mytool.py"] 
for opt, optname in zip("-a -x -p".split(), "address port pass".split()): 
    args.extend([opt, str(servers[server][optname])]) 
args.extend("some additional command".split()) 

# run script 
p = Popen([sys.executable or 'python'] + args, stdout=PIPE) 
# use p.stdout here... 
p.stdout.close() 
p.wait() 

Обратите внимание, что передача shell=True для команд с внешним входом является риском для безопасности, как это описано предупреждением in the docs.

2

Когда вы вызываете subprocess.Popen, вы можете передать либо строку, либо список для команды, которую нужно запустить. Если вы передаете список, элементы должны быть разделены определенным образом.

В вашем случае, вам нужно разделить это что-то вроде этого:

command = ["python", "mytool.py", "-a", servers[server]['address'], 
      "-x", servers[server]['port'], 
      "-p", servers[server]['pass'], 
      "some", "additional", "command"] 
p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) 

Это происходит потому, что если вы передаете в списке, Popen предполагает, что вы уже разделить командную строку на слова (значения, которые были бы в конечном итоге в sys.argv), так что это не нужно.

Как вы его называете, он попытается запустить двоичный файл под названием «python mytool.py -a», что вы не имеете в виду.

Другой способ исправить это состоит в том, чтобы соединить все слова в строку (которая затем разделит Popen - см. subprocess.list2cmdline). Но вам лучше использовать версию списка, если это возможно, - это упрощает контроль над разделением командной строки (если, например, аргументы содержат пробелы или кавычки) без необходимости возиться с цитированием кодовых символов.

+0

Переменная, которую я использую для хранения вывода, но на распечатке пустой (что, я думаю, не было выполнено). – GaNi

+0

Я думаю, вы имеете в виду это, когда читаете с.stdout, нет выхода? Это произойдет потому, что команда не запускается. – babbageclunk

+0

Собственно, оболочка = Истина, вероятно, загрязняет воду здесь - если вы не используете globbing (чтобы развернуть список файлов, скажем), лучше отключить его. – babbageclunk

1

Вы должны объединить команду целой строки:

p = subprocess.Popen("python mytool.py -a " + servers[server]['address'] + " -x " + servers[server]['port'] + " -p " + servers[server]['pass'] + " some additional command", shell=True, stdout=subprocess.PIPE) 
+0

У меня есть выход, сохраненный в переменную, но нет результата или трассы исполняемого скрипта. может быть прямой вывод ошибки, чтобы проверить его? – GaNi

+0

Добавьте «stderr = subprocess.PIPE» также – ciphor

1

Ваша проблема в типе str для первого Popen аргумента. Замените его на list. Ниже код может работать:

address = servers[server]['address'] 
port = servers[server]['port'] 
pass = servers[server]['pass'] 

command = "python mytool.py -a %s -x %d -p %s some additional command" % (address, port, pass) 
p = subprocess.Popen(command.split(), shell=True, stdout=subprocess.PIPE) 
#     ^^^^^^^^^^^^^^^ 

Кроме того, вы можете играть с shell, потому что это система, зависит параметр.

+0

Если бы аналогичная проблема, как раньше, но я решил ее сейчас. Благодаря :) – GaNi

Смежные вопросы