2015-01-26 2 views
0

мне нужно, чтобы выполнить эту строку в мой питон скрипт:Python: subprocess.Popen с параметрами и пути

p = subprocess.Popen(["python ~/mrjobScript.py ~/jobs/"+date+"/input/* > ~/jobs/"+date+"/output/output-"+domain+".log","--domain "+domain],stdout=subprocess.PIPE, shell=True) 

Однако --domain переключатель должен прийти сразу после mrjobScript.py. Как достичь?

+1

не размещать команду в списке, используя shell = True, также '' 'не будет работать, просто перенаправляя вывод в объект файла –

+0

Поскольку вы пытаетесь вызвать Python с Python, это может иметь больше смысла для простого импорта целевого модуля и непосредственного вызова его функций. Затем вы можете передавать аргументы командной строки гораздо более естественно, чем через подпроцесс и ОС. – merlin2011

+0

@ merlin2011, который не является вариантом с mapreduce (mrjob), или, по крайней мере, я не знаю, как, потому что есть задания, порожденные и т. Д. – nottinhill

ответ

1

Предполагая, что ваша команда работает в командной строке, а затем удалите аргумент stdout, изменяя порядок аргументов, и передавая строку вместо списка должно быть достаточно, чтобы сделать его воспроизвести поведение по команде линия.

import subprocess 
subprocess.Popen("python ~/mrjobScript.py --domain {1} ~/jobs/{0}/input/* > ~/jobs/{0}/output/output-{1}.log ".format(date,domain), shell=True) 

Обратите внимание, что это запустит подпроцесс, а затем перейдет к следующей строке вашего кода. Ваш код не будет ждать его. Если вы хотите, чтобы ваш код дождался его, вы можете вместо этого использовать subprocess.call.

Нота Предупреждение: Рекомендуется, чтобы пользователь shell=True консультации this answer, чтобы полностью понять последствия такого использования. В частности, такие приложения никогда не должны позволять переданным пользователем аргументам прямо или косвенно передавать аргумент вызова subprocess.Popen с shell=True без дезинфекции.

+0

Работает безупречно. – nottinhill

+0

using shell = True обычно очень плохая идея –

+0

@PadraicCunningham, Хотя это обычная мудрость, у меня есть три комментария.1) Обычный аргумент - это безопасность, и мы не видим очевидных доказательств того, что OP передает предоставленные пользователем аргументы в свой собственный сценарий. 2) Если бы это было не так, то было бы удалено Python 3, и это было не так. 3) Прагматизм. Время разработки драгоценное, а изгиб назад, чтобы имитировать функциональность оболочки внутри вашей собственной программы, не является прагматичным. – merlin2011

2

Вы не используете список с оболочкой = True, вы также должны перенаправить вывод в файл, чтобы сохранить его в файле.

import os 
from subprocess import check_call 
pt1 = os.path.expanduser("~/mrjobScript.py") 
pt2 = os.path.expanduser("~/jobs/{}/input/*".format(date) 

with open (os.path.expanduser("~/jobs/{}/output/output-{}.log".format(date,domain)),"w") as f: 
    subprocess.check_call(["python",pt1,"--domain",domain,pt2],stdout=f) 
+0

Почему вы отформатировали дату? это не обязательно imho. мой mrjobsscript принимает дату так же, как я передаю ее. – nottinhill

+1

@SirBenBenji, что вы подразумеваете под форматом? Я просто делаю код более чистым, используя str.format для соединения вместо + –

+0

'p = subprocess.check_output ([" python "," - domain ", domainNoTld, pt1, pt2], stdout = f) Файл" /usr/lib/python2.7/subprocess.py ", строка 565, в check_output повысить значение ValueError (аргумент stdout не разрешен, он будет переопределен.) ValueError: аргумент stdout не разрешен, он будет переопределен.' – nottinhill

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