Невозможно передать аргумент python с помощью "#! / Usr / bin / env python" - PullRequest
64 голосов
/ 22 июля 2010

Мне нужно было иметь непосредственно исполняемый скрипт Python, поэтому я начал файл с #!/usr/bin/env python. Тем не менее, мне также нужен небуферизованный вывод, поэтому я попытался #!/usr/bin/env python -u, но это не с python -u: no such file or directory.

Я обнаружил, что #/usr/bin/python -u работает, но мне нужно, чтобы получить python в PATH для поддержки виртуальных env сред.

Какие у меня варианты?

Ответы [ 9 ]

40 голосов
/ 29 января 2012

В некоторых средах env не разделяет аргументы.Так что ваш env ищет "python -u" на вашем пути.Мы можем использовать sh, чтобы обойти.Замените свой shebang следующими строками кода, и все будет хорошо.

#!/bin/sh
''''exec python -u -- "$0" ${1+"$@"} # '''
# vi: syntax=python

ps нам не нужно беспокоиться о пути к sh, верно?

21 голосов
/ 06 июня 2013

Лучше использовать переменную окружения, чтобы включить это.Смотрите документ Python: http://docs.python.org/2/using/cmdline.html

для вашего случая:

export PYTHONUNBUFFERED=1
script.py
13 голосов
/ 19 января 2012

Когда вы используете shebang в Linux, вся остальная часть строки после имени интерпретатора интерпретируется как один аргумент.python -u передается env, как если бы вы набрали: /usr/bin/env 'python -u'./usr/bin/env ищет двоичный файл с именем python -u, которого нет.

12 голосов
/ 22 июля 2010

Передача аргументов в строку shebang не является стандартной и, как вы экспериментировали, не работает в сочетании с env в Linux. Решение с помощью bash заключается в использовании встроенной команды «set» для установки необходимых параметров. Я думаю, вы можете сделать то же самое, чтобы установить небуферизованный вывод stdin с помощью команды python.

my2c

9 голосов
/ 31 июля 2014

Вот сценарий, альтернативный / usr / bin / env, который разрешает передачу аргументов в строке хэш-взрыва, основанный на / bin / bash и с ограничением, что пробелы в исполняемом пути запрещены Я называю это "envns" (env No Пробелы):

#!/bin/bash

ARGS=( $1 )  # separate $1 into multiple space-delimited arguments.
shift # consume $1

PROG=`which ${ARGS[0]}`
unset ARGS[0] # discard executable name

ARGS+=( "$@" ) # remainder of arguments preserved "as-is".
exec $PROG "${ARGS[@]}"

Предполагая, что этот скрипт находится в / usr / local / bin / envns, вот ваша строка shebang:

#!/usr/local/bin/envns python -u

Протестировано на Ubuntu 13.10 и cygwin x64.

7 голосов
/ 29 января 2014

Это может быть немного устаревшим, но руководство env (1) говорит, что для этого случая можно использовать '-S'

#!/usr/bin/env -S python -u

Кажется, это работает довольно хорошо на FreeBSD.

5 голосов
/ 22 июля 2010

Это Kludge и требует Bash, но он работает:

#!/bin/bash

python -u <(cat <<"EOF"
# Your script here
print "Hello world"
EOF
)
4 голосов
/ 24 ноября 2015

Исходя из ответа Ларри Кая, env позволяет вам установить переменную непосредственно в командной строке. Это означает, что -u можно заменить на эквивалентную настройку PYTHONUNBUFFERED перед python:

#!/usr/bin/env PYTHONUNBUFFERED="YESSSSS" python

Работает на RHEL 6.5. Я почти уверен, что функция env почти универсальна.

0 голосов
/ 26 мая 2017

Я недавно написал патч для GNU Coreutils версии env для решения этой проблемы:

http://lists.gnu.org/archive/html/coreutils/2017-05/msg00018.html

Если у вас есть это, вы можете сделать:

#!/usr/bin/env :lang:--foo:bar

env разделит :lang:foo:--bar на поля lang, foo и --bar.Он будет искать PATH для интерпретатора lang, а затем вызывать его с аргументами --foo, bar, плюс путь к сценарию и аргументы этого сценария.

Существует также функция дляпередать имя сценария в середине вариантов.Предположим, вы хотите запустить lang -f <thecriptname> other-arg, а затем остальные аргументы.С этим исправленным env это делается следующим образом:

#!/usr/bin/env :lang:-f:{}:other-arg

Крайнее левое поле, эквивалентное {}, заменяется следующим первым аргументом, который при вызове взрыва хеша являетсяимя сценарияЭтот аргумент затем удаляется.

Здесь other-arg может быть чем-то, обработанным lang, или, возможно, чем-то, обработанным скриптом.

Чтобы лучше понять, см. Многочисленный тест echoслучаи в патче.

Я выбрал символ :, потому что это существующий разделитель, используемый в PATH в системах POSIX.Поскольку env выполняет поиск PATH, маловероятно, что он будет использоваться для программы, имя которой содержит двоеточие.Маркер {} происходит от утилиты find, которая использует его для обозначения вставки пути в командную строку -exec.

...