Должен ли я поставить #! (Шебанг) ​​в скриптах Python, и какую форму это должно принять?

830

Должен ли я добавить Шебанг в мои скрипты Python? В какой форме?

#!/usr/bin/env python 

или

#!/usr/local/bin/python

Они одинаково портативны? Какая форма используется чаще всего?

Примечание: смерч проект использует хижину. С другой стороны,проект Django этого не делает.

treecoder
источник
70
Второй не является переносимым и выйдет из строя на многих компьютерах, если не на большинстве.
Дитрих Эпп
4
Как #!/usr/bin/pythonсравнить с первым вариантом? Я вижу это во многих примерах кода. Редактировать: Может быть, это ответ .. stackoverflow.com/a/2429517/1156245
геотеория
1
Я говорю всегда использовать это, почему? «Zen Of Python» - Строка 2 - «Явное лучше, чем неявное». python.org/dev/peps/pep-0020
JayRizzo
2
Честно говоря, ни то, ни другое не является правильным, потому что вы, как автор, не знаете, где будет правильная версия Python при запуске скрипта. Это должно быть задачей установщика, чтобы добавить правильный shebang.
Чепнер

Ответы:

1118

Строка shebang в любом сценарии определяет возможность выполнения сценария как автономный исполняемый файл без pythonпредварительного ввода в терминале или двойного щелчка по нему в файловом менеджере (при правильной настройке). В этом нет необходимости, но, как правило, это делается, поэтому, когда кто-то видит файл, открытый в редакторе, он сразу же узнает, на что он смотрит. Тем не менее, что притон линия используется IS важно.

Правильное использование для скриптов Python 3:

#!/usr/bin/env python3

По умолчанию это версия 3.latest. Для Python 2.7.Последнее использование python2вместо python3.

Следующее НЕ должно использоваться (за исключением редкого случая, когда вы пишете код, совместимый с Python 2.x и 3.x):

#!/usr/bin/env python

Причина этих рекомендаций, приведены в PEP 394 , что pythonможет относиться либо к python2или python3на разных системах. В настоящее время он относится к python2большинству дистрибутивов, но в какой-то момент он может измениться.

Кроме того, НЕ используйте:

#!/usr/local/bin/python

«В этих случаях python может быть установлен в / usr / bin / python или / bin / python, приведенный выше #! завершится ошибкой».

- "#! / usr / bin / env python" против "#! / usr / local / bin / python"

GlassGhost
источник
4
@EliasVanOotegem Если вы не можете быть уверены, что Python будет найден в, /usr/binто как вы можете быть уверены, что envон будет найден в /usr/bin. Если python установлен в нестандартном месте, то это, вероятно, означает, что python настроен нестандартным способом и в результате скрипт должен быстро завершиться с ошибкой. В отличие от предположений о свойствах интерпретатора Python и надежды на лучшее.
Дюны
65
@Dunes: envбудет всегда можно найти в /usr/bin/, и его работа состоит в том, чтобы найти контейнеры (например , питон) , используя PATH. Независимо от того, как установлен python, его путь будет добавлен в эту переменную и envнайдет его (если нет, python не установлен). Это работа env, вот и вся причина, почему она существует. Это то, что предупреждает об окружающей среде (настраивает переменные env, включая пути установки и включают пути). Люди всегда понимали, что эта команда может работать, только если она всегда находится в одном и том же месте. Это просто дано
Элиас Ван Отегем
3
@JFSebastian: Вы правы, это не гарантировано или не поддерживается стандартом POSIX. Я предположил, что это произошло из-за того, что одна из более поздних версий IEEE содержала кое-что из окружения. В любом случае: нет, /usr/bin/envне гарантируется никаким стандартом, кроме широко (повсеместно принятого) принятого правила ...
Элиас Ван Отегем
6
Если вы используете virtualenv, #! / Usr / local / bin / python, даже если он существует, ошибается.
нули
6
Одна проблема с этим: согласно PEP394 следует использовать pythonисполняемый файл, только когда скрипт совместим с Python 2 и Python 3. В противном случае он должен указывать на соответствующий выбор из python2и python3.
amiller27
67

Это действительно просто вопрос вкуса. Добавление shebang означает, что люди могут вызывать скрипт напрямую, если они хотят (при условии, что он помечен как исполняемый); опуская это просто означает, pythonчто должен быть вызван вручную.

Конечный результат запуска программы не зависит ни в каком случае; это просто варианты средств.

янтарный
источник
3
Вот только это - не имеет значения, какую сторону вы выбираете, потому что нет «правильной» стороны. Это абсолютно субъективное решение.
Янтарная
5
Не более, чем любое другое тривиальное решение. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber
2
Как я могу выполнить файл python напрямую без команды 'python'?
Дзен
5
@Zen Предполагая, что вы включили shebang (#! / Usr / bin / env python) в ваш скрипт, вам просто нужно сделать его исполняемым. Нечто подобное chmod a+x [your-script].pyдолжно сделать его исполняемым, и тогда вы можете просто вызвать ./[your-script.py]оболочку.
skålfyfan
9
В ответ на GlassGhost указывает, есть это преимущество в бетон включая его , кроме вкуса: это ясно для читателя будущего файла , который они читают исполняемый скрипт, а не файл , который предназначается , чтобы быть импортированы. Подобно модификаторам управления публичным / частным доступом на языках, в которых они есть, шебанги полезны как документация, а также для их фактического эффекта, а в некоторых случаях аспект документации фактически имеет наибольшее значение.
Марк Эмери
32

Должен ли я добавить Шебанг в мои скрипты Python?

Поместите шебанг в скрипт Python, чтобы указать:

  • этот модуль можно запустить как скрипт
  • может ли он быть запущен только на python2, python3 или совместим с Python 2/3
  • в POSIX это необходимо, если вы хотите запустить скрипт напрямую, без pythonявного вызова исполняемого файла

Они одинаково портативны? Какая форма используется чаще всего?

Если вы пишете шебанг вручную, всегда используйте, #!/usr/bin/env pythonесли у вас нет особых причин не использовать его. Эта форма понятна даже в Windows (Python Launcher).

Примечание: установленные скрипты должны использовать определенный исполняемый файл python, например, /usr/bin/pythonили /home/me/.virtualenvs/project/bin/python. Плохо, если какой-то инструмент ломается, если вы активируете virtualenv в своей оболочке. К счастью, в большинстве случаев правильный шебанг создается автоматически setuptoolsили инструментами вашего дистрибутива (в Windows setuptoolsможно .exeавтоматически генерировать сценарии оболочки ).

Другими словами, если скрипт находится в исходной проверке, то вы, вероятно, увидите #!/usr/bin/env python . Если он установлен, то shebang - это путь к конкретному исполняемому файлу python, например #!/usr/local/bin/python (ПРИМЕЧАНИЕ: вы не должны писать пути из последней категории вручную).

Для того, чтобы выбрать , следует ли использовать python, python2или python3в притон, см PEP 394 - The «питон» Command на Unix-подобных системах :

  • ... pythonследует использовать в строке shebang только для сценариев, которые совместимы с исходным кодом для Python 2 и 3.

  • при подготовке к возможному изменению версии Python по умолчанию только сценарии Python 2 должны быть либо обновлены, чтобы быть совместимыми с исходным кодом Python 3, либо использовать их python2в строке shebang.

JFS
источник
3
Первый ответ, который даже относится к PEP, не имеет достаточного количества голосов. А? Есть ли ПКП для #!/usr/bin/env pythonсебя?
Бинки
Пожалуйста, не используйте #!/usr/bin/env python. Пожалуйста, не предлагайте «всегда использовать» #!/usr/bin/env python. Это неправильно в 99% случаев (причина, которую вы указали в своем ответе).
Джей Салливан
1
@JaySullivan Вы понимаете разницу между проверкой исходного кода и установленными сценариями? Я поддерживаю предложение. Это работает хорошо.
JFS
1
@jfs: перечитав мой комментарий, я вижу, как мне не удалось донести свою мысль. Я имел в виду, что большинство людей захотят использовать «python2» или «python3», а не «python». Независимо от того, решите ли вы с помощью полного пути или env, что технически было вопросом OP, вы ответили, и я не согласен с этим.
Джей Салливан
@JaySullivan Я согласен. Ты читал цитату из бодрости духа в ответе. Это говорит то же самое.
JFS
15

Если у вас более одной версии Python и сценарий должен работать под определенной версией, она может убедиться, что правильная версия используется при непосредственном выполнении сценария, например:

#!/usr/bin/python2.7

Обратите внимание, что скрипт все еще может быть запущен через полную командную строку Python или через импорт, и в этом случае она игнорируется. Но для сценариев, запускаемых напрямую, это достойная причина для использования she-bang.

#!/usr/bin/env python как правило, лучший подход, но это помогает в особых случаях.

Обычно было бы лучше создать виртуальную среду Python, и в этом случае универсальный #!/usr/bin/env pythonтип идентифицировал бы правильный экземпляр Python для virtualenv.

Крис Джонсон
источник
Разве пространство не приведет к его провалу?
RandomInsano
1
@ RandomInsano, я так не думаю. Пространства кажутся довольно распространенными, и существует множество свидетельств того, как это принято. Тем не менее, я думаю, что нет-пространство, вероятно, более каноническое использование.
Крис Джонсон
1
Вы определенно правы в этом. Только что протестировал на bash и tcsh.
RandomInsano
Результат whichдаст вам строку, которая будет работать, точка. Вам не нужно беспокоиться о любой из кишок, чтобы использовать его.
SDsolar
10

Вы должны добавить шебанг, если скрипт предназначен для выполнения. Вам также следует установить скрипт с установочным программным обеспечением, которое изменяет shebang на что-то правильное, чтобы оно работало на целевой платформе. Примерами этого являются distutils и Distribute.

Леннарт Регебро
источник
1
Вам не нужно изменять #! линия потом. Вот для чего / usr / bin / env. Жесткое кодирование конкретного интерпретатора Python может принести больше вреда, чем пользы. Это очень хрупко в отношении установки другой версии Python или переключения между Python нашего дистрибутива по сравнению с пользовательской установкой Python.
Vog
В Ubuntu использование результатов whichавтоматически выберет значение по умолчанию, которое используется системными командами и тому подобное. Он универсален, и система направляет его на правильную установку.
SDsolar
9

Цель shebang - чтобы скрипт распознал тип интерпретатора, когда вы хотите выполнить скрипт из оболочки. В основном, и не всегда, вы выполняете сценарии, предоставляя интерпретатор извне. Пример использования:python-x.x script.py

Это будет работать, даже если у вас нет декларатора shebang.

Почему первый вариант более «переносим», потому что он /usr/bin/envсодержит вашу PATHдекларацию, которая учитывает все пункты назначения, в которых находятся исполняемые файлы вашей системы.

ПРИМЕЧАНИЕ: Торнадо не строго использует шебанги, а Джанго строго не использует. Это зависит от того, как вы выполняете основную функцию вашего приложения.

ТАКЖЕ: это не зависит от Python.

meson10
источник
8

Иногда, если ответ не очень ясен (я имею в виду, что вы не можете решить, да или нет), тогда он не имеет большого значения, и вы можете игнорировать проблему, пока ответ не будет ясным.

#!Единственная цель для запуска скрипта. Django загружает источники самостоятельно и использует их. Никогда не нужно решать, какой переводчик следует использовать. Таким образом, на #!самом деле здесь нет никакого смысла.

Как правило, если это модуль и его нельзя использовать в качестве сценария, использовать его не нужно #!. С другой стороны, источник модуля часто содержит, if __name__ == '__main__': ...по крайней мере, некоторые тривиальные тесты функциональности. Тогда это #!снова имеет смысл.

Одна хорошая причина для использования #!- когда вы используете оба сценария Python 2 и Python 3 - они должны интерпретироваться различными версиями Python. Таким образом, вы должны помнить, что pythonнужно использовать при запуске скрипта вручную (без #!внутренней части). Если у вас есть смесь таких сценариев, рекомендуется использовать#! внутри, сделать их исполняемыми и запустить их как исполняемые файлы (chmod ...).

При использовании MS-Windows это #!не имело смысла - до недавнего времени. Python 3.3 представляет Windows Python Launcher (py.exe и pyw.exe), который читает #!строку, обнаруживает установленные версии Python и использует правильную или явно требуемую версию Python. Поскольку расширение может быть связано с программой, вы можете получить такое же поведение в Windows, как и с флагом выполнения в системах на основе Unix.

pepr
источник
3

Когда я недавно установил Python 3.6.1 в Windows 7, он также установил Python Launcher для Windows, который должен обрабатывать строку shebang. Однако я обнаружил, что Python Launcher этого не делал: строка shebang игнорировалась, и всегда использовался Python 2.7.13 (если я не выполнял скрипт с использованием py -3).

Чтобы это исправить, мне пришлось отредактировать раздел реестра Windows HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Это все еще имело значение

"C:\Python27\python.exe" "%1" %*

из моей предыдущей установки Python 2.7. Я изменил значение этого ключа реестра на

"C:\Windows\py.exe" "%1" %*

и обработка строки Python Launcher shebang работала, как описано выше.

ETalbot
источник
2

Если у вас установлены разные модули и вам нужно использовать определенную установку на python, тогда shebang сначала будет ограничен. Тем не менее, вы можете сделать трюки, подобные приведенным ниже, чтобы позволить shebang вызываться сначала как сценарий оболочки, а затем выбрать python. Это очень гибкий имо:

#!/bin/sh
#
# Choose the python we need. Explanation:
# a) '''\' translates to \ in shell, and starts a python multi-line string
# b) "" strings are treated as string concat by python, shell ignores them
# c) "true" command ignores its arguments
# c) exit before the ending ''' so the shell reads no further
# d) reset set docstrings to ignore the multiline comment code
#
"true" '''\'
PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    echo Using preferred python $PREFERRED_PYTHON
    exec $PREFERRED_PYTHON "$0" "$@"
elif [ -x $ALTERNATIVE_PYTHON ]; then
    echo Using alternative python $ALTERNATIVE_PYTHON
    exec $ALTERNATIVE_PYTHON "$0" "$@"
else
    echo Using fallback python $FALLBACK_PYTHON
    exec python3 "$0" "$@"
fi
exit 127
'''

__doc__ = """What this file does"""
print(__doc__)
import platform
print(platform.python_version())

Или еще лучше, возможно, чтобы облегчить повторное использование кода в нескольких скриптах Python:

#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[@]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$@"; exit 127; '''

а затем select.sh имеет:

PREFERRED_PYTHON=/Library/Frameworks/Python.framework/Versions/2.7/bin/python
ALTERNATIVE_PYTHON=/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
FALLBACK_PYTHON=python3

if [ -x $PREFERRED_PYTHON ]; then
    CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
    CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
    CHOSEN_PYTHON=$FALLBACK_PYTHON
fi
Нил МакГилл
источник
1
Хотя я не уверен, что подобный полиглот является хорошей практикой в ​​целом, это, безусловно, очень интересный подход и, возможно, самый гибкий ответ здесь.
Райан Амос
1
Очень круто. Я не знал, что вы могли бы сделать это
user2233949
1

Ответ: Только если вы планируете сделать это исполняемым скриптом командной строки.

Вот процедура:

Начните с проверки правильной строки shebang для использования:

which python

Возьмите вывод из этого и добавьте его (с символом #!) В первой строке.

В моей системе это выглядит так:

$which python
/usr/bin/python

Итак, ваш шебанг будет выглядеть так:

#!/usr/bin/python

После сохранения он все равно будет работать, как прежде, так как python увидит эту первую строку в качестве комментария.

python filename.py

Чтобы сделать это командой, скопируйте ее, чтобы удалить расширение .py.

cp filename.py filename

Скажите файловой системе, что это будет исполняемый файл:

chmod +x filename

Чтобы проверить это, используйте:

./filename

Лучше всего переместить его куда-нибудь в $ PATH, чтобы все, что вам нужно было ввести, - это само имя файла.

sudo cp filename /usr/sbin

Таким образом, он будет работать везде (без ./ перед именем файла)

SDsolar
источник
Я сомневаюсь, что это лучшая практика, и я настоятельно рекомендую использовать решение GlassGhost .
Колидир
Я нашел это полезным, и это прекрасно сработало для меня. это было хорошо объяснено. Я был бы признателен за комментарии, указывающие, почему это не лучшая практика, однако. Я стремлюсь учиться.
Чарльз Карьер
0

Абсолют против логического пути:

Это действительно вопрос о том, должен ли путь к интерпретатору Python быть абсолютным или логическим ( /usr/bin/env) в отношении переносимости.

Встречаясь с другими ответами на этом и других сайтах стека, которые обсуждали проблему в общем виде без поддержки доказательств, я провел по-настоящему, действительно , детальное тестирование и анализ этого вопроса на unix.stackexchange.com . Вместо того, чтобы вставлять этот ответ сюда, я укажу интересующимся сравнительным анализом на этот ответ:

https://unix.stackexchange.com/a/566019/334294

Будучи инженером Linux, моя цель всегда состоит в том, чтобы предоставить наиболее подходящие, оптимизированные хосты для моих клиентов-разработчиков, поэтому вопрос о средах Python был тем, на что мне действительно требовался твердый ответ. Мое мнение после тестирования состояло в том, что логический путь в «челке» был лучшим из (2) вариантов.

F1Linux
источник
-3

Используйте сначала

which python

Это даст вывод в качестве места, где присутствует мой интерпретатор Python (двоичный).

Этот вывод может быть любым, таким как

/usr/bin/python

или

/bin/python

Теперь соответствующим образом выберите линию Шебанга и используйте ее.

Для обобщения мы можем использовать:

#!/usr/bin/env

или

#!/bin/env
frp farhan
источник
3
Это, скорее всего, не будет переносимым на другие системы. #!/usr/bin/envделает правильный выбор для вас.
фрагментарная
Вот почему вы используете whichкоманду - она ​​вернет правильную строку для вашей конкретной системы.
SDsolar
1
... и затем каждый раз, когда сценарий должен выполняться на другой машине, вы запускаете which pythonснова и меняете сценарий, если выходные данные отличаются от текущего shebang
фрагментированная
2
-1 Это самое хрупкое из возможных решений. Гарантируется, что он будет правильным только для системы, в которой написан ваш скрипт на python. Используйте #! / Usr / bin / env python3 для переносимости
Myles Hollowed