#python #makefile
#python #makefile
Вопрос:
С помощью следующего файла Makefile:
datetime := $(shell date %Y%m%d%H%M%S)
target := $(shell echo $$TARGET)
dothis:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns('1', '2', '3'));
"
dothat:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns('1', '2', '3'));
print('done')"
Я могу
$ TARGET=folder1 make dothis
и
$ TARGET=folder2 make dothat
Где dothis
выполняется скрипт Pyhton и dothat
выполняется другой скрипт Python, $target
приходит из командной строки и заменяется в скрипте Python.
В обоих случаях я передаю список ignore_patterns
, поскольку список для dothis
одинаков, и dothat
я думаю определить его только один раз в Makefile и передать его в скрипте Python в качестве переменной, как я делаю для datetime
.
Как я могу преобразовать список Bash / Makefile в список Python?
Я попробовал следующее, хотя это не работает.
datetime := $(shell date %Y%m%d%H%M%S)
target := $(shell echo $$TARGET)
list := $(1 2 3)
dothis:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns($(list)));
"
dothat:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns($(list)));
print('done')"
Комментарии:
1. Вы пробовали
sys.argv
и передавали список в качестве аргументов скрипту?2. На самом деле я хотел бы, чтобы список в скрипте не передавался
Ответ №1:
make
не содержит списков или даже чисел. В нем просто есть строки. Но этого должно быть достаточно для ваших целей.
Однако, прежде чем мы перейдем к этому, несколько комментариев к вашему примеру кода:
-
если ваша единственная цель установки
TARGET
переменной окружения — иметь возможность передавать ее значение вtarget
макрос makefile, тогда вы черпаете вдохновение у Рубе Голдберга. Вы можете задаватьmake
макросы непосредственно в командной строке — назначения просто должны отображаться в качестве аргументов дляmake
:make target=folder1 dothis
или
make dothat target=folder2
-
В makefile
$()
синтаксис запрашивает расширение макроса или (только GNU make) вызова функции.$(1 2 3)
не выражает ни того, ни другого, потому что1 2 3
это недопустимое имя переменной и1
это не имя какой-либо встроенной функции. Вам не нужны специальные разделители вокруг буквенного текстаmake
значения макроса. -
Вам не нужен или особенно нужен список Python для аргумента
shutil.ignore_patterns()
. Все, что вам нужно, это последовательность аргументов, разделенных запятыми. Если вы планируете представлять globs, вам нужно будет указать соответствующие цитаты на Python, но дляmake
вам не нужны никакие специальные цитаты. -
Если у вас есть правило make, рецепт которого на самом деле не создает целевой объект (в виде файла), то обычно неплохо предупредить
make
об этом, обозначив целевые объекты таких правил как предварительные условия специального целевого объекта.PHONY
. Это GNU-изм, но он должен быть безвреден дляmake
тех, кто его не понимает, и вы все равно уже полагаетесь на функции, специфичные для GNU.
Что-то вроде этого должно сработать:
datetime := $(shell date %Y%m%d%H%M%S)
# Default to the current working directory; can be overridden on the command line:
target := .
# The arguments to to shutil.ignore_patterns, which are text to `make`:
ignore := 1, 2, 3
dothis:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns($(ignore)))"
dothat:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns($(ignore)));
print('done')"
.PHONY: dothis dothat
ОДНАКО в данном конкретном случае я бы пошел дальше. Ваши два скрипта на Python идентичны, за исключением того, включают ли они print('done')
инструкцию. Зачем все это повторять? Есть несколько способов избежать повторения, но это один из самых простых:
datetime := $(shell date %Y%m%d%H%M%S)
# Default to the current working directory; can be overridden on the command line:
target := .
# The arguments to to shutil.ignore_patterns, which are text to `make`:
ignore := 1, 2, 3
dothis:
@python -c "import shutil ;
from shutil import copytree, ignore_patterns;
shutil.copytree('$(target)', 'target-$(datetime)', ignore=ignore_patterns($(ignore)))"
# First, build target dothis, then print "done":
dothat: dothis
echo done
.PHONY: dothis dothat
Комментарии:
1. Почему вы вызываете
target
макрос? Могу ли я назвать это переменной?2. @KcFnMi, «макрос» — это терминология, используемая POSIX. «Переменная» является часто используемой альтернативой. Вы можете использовать любой из них, но данный случай на самом деле показателен, если вместо этого вы посмотрите на
ignore
макрос / переменную. Расширение до1, 2, 3
, как я уже предлагал, того, что является фрагментом более крупного выражения на другом языке, скорее более похоже на макросы и скорее менее похоже на переменные, по крайней мере, для меня.