python subprocess.call() изменяет аргументы перед передачей его в shell-скрипт?
Я пишу оболочку Python для вызова программ из пакета AMOS (специально для объединения сборок генома из разных источников, используя хороший старый minimus2 из AMOS).
Сценарии должны вызываться следующим образом при непосредственном использовании оболочки:
toAmos -s myinput.fasta -o testoutput.afg
minimus2 testoutput -D REFCOUNT=400 -D OVERLAP=500
[только для уточнения:
-toAmos: преобразует мой файл input.fasta в формат.afg и требует аргумент входной последовательности ("-s") и выходной аргумент ("-o")
-minimus2: объединяет набор данных последовательности со ссылочными контигами и требует аргумент "-D REFCOUNT=x" для указания количества последовательностей повторных ссылок в вводе и аргумент "-D OVERLAP=Y" для определения минимального перекрытия между последовательностями]
Поэтому в моем скрипте я использую subprocess.call() для вызова необходимых инструментов AMOS.
В основном я делаю это:
from subprocess import call:
output_basename = "testoutput"
inputfile = "myinput.fasta"
call(["toAmos", "-s " + inputfile, "-o " + output_basename + ".afg"])
call(["minimus2", output_basename, "-D REFCOUNT=400", "-D OVERLAP=500"])
Но в этом случае инструменты AMOS не могут больше интерпретировать аргументы. Кажется, что аргументы модифицируются subprocess.call() и передаются неправильно. Я получаю сообщение об ошибке:
Unknown option: s myinput.fasta
Unknown option: o testoutput.afg
You must specify an output AMOS AFG file with option -o
/home/jov14/tools/miniconda2/bin/runAmos: unrecognized option '-D REFCOUNT=400'
Command line parsing failed, use -h option for usage info
Кажется, аргументы передаются без начального "-"? Поэтому я попытался передать команду в виде одной строки (включая аргументы) следующим образом:
call(["toAmos -s " + inputfile +" -o " + output_basename + ".afg"])
Но тогда я получаю эту ошибку...
OSError: [Errno 2] No such file or directory
... предположительно потому, что subprocess.call интерпретирует всю строку как имя для одного скрипта. Я думаю, я мог бы попробовать shell=True
как обходной путь, но Интернет полон инструкций, явно советующих против этого.
В чем здесь проблема? Что я могу сделать?
2 ответа
ответ
Либо сделать:
call("toAmos -s " + inputfile +" -o " + output_basename + ".afg") # single string
или сделать:
call(["toAmos", "-s", inputfile, "-o", output_basename + ".afg"]) # list of arguments
обсуждение
В случае вашего:
call(["toAmos", "-s " + inputfile, "-o " + output_basename + ".afg"])
Вы должны предоставить:
- или
"-s" + inputfile
(нет места после-s
),"-o" + output_basename + ".afg"
- или же
"-s", inputfile
(отдельные аргументы),"-o", output_basename + ".afg"
В случае вашего:
call(["minimus2", output_basename, "-D REFCOUNT=400", "-D OVERLAP=500"])
"-D REFCOUNT=400"
а также "-D OVERLAP=500"
должны быть представлены как два предмета каждый ('-D', 'REFCOUNT=400', '-D', 'OVERLAP=500'
), или отбросьте пробелы ('-DREFCOUNT=400', '-DOVERLAP=500'
).
Дополнительная информация
Кажется, вам не хватает знаний о том, как оболочка разделяет командную строку; Я предлагаю вам всегда использовать однострочный метод, если в именах файлов нет пробелов или вы не должны использовать shell=False
вариант; в этом случае я предлагаю вам всегда предоставлять список аргументов.
-s
и после имени входного файла должны быть отдельные аргументы call
, так как они находятся в командной строке:
call(["toAmos", "-s", inputfile, "-o", output_basename + ".afg"])