Чи слід ставити #! (shebang) в сценаріях Python, і в якій формі він повинен мати?


828

Чи слід вводити шебанг у свої сценарії Python? У якій формі?

#!/usr/bin/env python 

або

#!/usr/local/bin/python

Вони однаково портативні? Яка форма використовується найбільше?

Примітка: смерч проект використовує хатину. З іншого боку,проект Django не робить.


70
Другий не є портативним і вийде з ладу на багатьох комп’ютерах, якщо не на більшості.
Дітріх Епп

4
Як #!/usr/bin/pythonпорівнювати перший варіант? Я бачу це в досить багато прикладу коду. Edit: Може бути , це відповідь .. stackoverflow.com/a/2429517/1156245
geotheory


1
Я кажу, завжди використовуйте це, навіщо? "Zen Of Python" - рядок 2 - "Явне краще, ніж неявне". python.org/dev/peps/pep-0020
JayRizzo

2
Відверто кажучи, і це не "правильно", тому що ви як автор не знаєте, де буде правильна версія Python, коли сценарій запускається. Вона повинна бути робота з монтажником , щоб додати правильну хатину.
чепнер

Відповіді:


1117

Рядок 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" vs "#! / usr / local / bin / python"


4
@EliasVanOotegem Якщо ви не можете бути впевнені, що python знайдеться в /usr/binто, як ви можете бути впевнені, що envце буде знайдено в /usr/bin. Якщо 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.


3
Перша відповідь навіть на посилання на ПЕП не має достатньо результатів. Так? Чи є PEP для #!/usr/bin/env pythonсебе?
binki

Будь ласка, не використовуйте #!/usr/bin/env python. Будь ласка, не пропонуйте "завжди використовувати" #!/usr/bin/env python. Це неправильно робити в 99% випадків (причина, яку ви включили у свою відповідь).
Джей Салліван

1
@JaySullivan Ви розумієте різницю між джерелом замовлення та встановленими сценаріями? Я стою за пропозицією. Це добре працює.
jfs

1
@jfs: Після перечитування коментаря я бачу, як я зовсім не зміг зрозуміти свою точку зору. Я мав на увазі те, що більшість людей захочуть використовувати "python2" або "python3", а не "python". Вирішити чи ні через повний шлях чи навколишнє середовище, що технічно було питанням про ОП, ви відповіли, і я не погоджуюся з цього приводу.
Джей Салліван

@JaySullivan Я згоден. Ви читали цитату з пеп у відповіді. Це говорить те саме.
jfs

15

Якщо у вас є більше однієї версії Python, і сценарій потрібно запускати під певною версією, she-bang може забезпечити правильне використання правильного сценарію, наприклад:

#!/usr/bin/python2.7

Зверніть увагу, що сценарій все ще може бути запущений через повний командний рядок Python або через імпорт, і в цьому випадку she-bang ігнорується. Але для сценаріїв, які виконуються безпосередньо, це гідна причина використовувати she-bang.

#!/usr/bin/env python як правило, кращий підхід, але це допомагає в особливих випадках.

Зазвичай було б краще створити віртуальне середовище Python, і в цьому випадку загальний #!/usr/bin/env pythonідентифікував би вірний екземпляр Python для virtualenv.


Хіба простір не спричинить його збій?
RandomInsano

1
@RandomInsano, я не думаю, що так. Простір здається досить поширеним, і навколо цього є чимало доказів як прийнятого використання. Однак я думаю, що простору, мабуть, є більш канонічне використання.
Кріс Джонсон

1
Ви точно маєте рацію на цьому. Щойно перевірена на bash та tcsh
RandomInsano

Результати whichдадуть вам рядок, який буде працювати, період. Вам не потрібно турбуватися про будь-яку кишку, щоб її використати.
SDsolar

10

Ви повинні додати шебанг, якщо сценарій призначений для виконання. Слід також встановити сценарій із встановленням програмного забезпечення, яке модифікує шебанг на щось правильне, щоб він працював на цільовій платформі. Прикладами цього є distutils і розподілити.


1
Вам не потрібно змінювати #! рядок після цього. Ось для чого / usr / bin / env. Жорстке кодування проти певного інтерпретатора Python може принести більше шкоди, ніж користі. Це дуже крихко щодо встановлення іншої версії Python або переключення між нашим дистрибутивом Python порівняно з власною установкою Python.
vog

В Ubuntu, використовуючи результати which, автоматично вибирається типовий параметр, який використовується системними командами тощо. Він є загальним, і система спрямовує його до належної установки.
SDsolar

9

Призначення shebang полягає в тому, щоб скрипт розпізнав тип інтерпретатора, коли потрібно виконати сценарій з оболонки. Переважно, і не завжди, ви виконуєте сценарії, поставляючи інтерпретатор зовні. Приклад використання:python-x.x script.py

Це спрацює, навіть якщо у вас немає декларатора шебанга.

Чому перший варіант є більш "портативним", тому що він /usr/bin/envмістить вашу PATHдекларацію, яка враховує всі місця призначення, де розміщені ваші виконуючі системи.

ПРИМІТКА: Торнадо суворо не використовує шебангів, а Джанго суворо. Це залежить від того, як ви виконуєте основну функцію програми.

ТАКОЖ: Це не відрізняється від Python.


8

Іноді, якщо відповідь не дуже чіткий (я маю на увазі, ви не можете вирішити, чи так, ні), це не має великого значення, і ви можете ігнорувати проблему, поки відповідь не буде зрозумілою.

#!Єдина мета для запуску скрипта. Джанго завантажує джерела самостійно та використовує їх. Ніколи не потрібно вирішувати, який перекладач слід використовувати. Таким чином, #!насправді тут немає сенсу.

Як правило, якщо це модуль і не може бути використаний як сценарій, немає необхідності у використанні #!. З іншого боку, джерело модуля часто містить 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.


3

Коли я нещодавно встановив Python 3.6.1 на Windows 7, він також встановив програму Python Launcher для Windows, яка повинна обробляти лінію shebang. Однак я виявив, що запуск Python не робив цього: рядок 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" %*

і обробка лінії shebang запуску Python Launcher працювала, як описано вище.


2

Якщо у вас встановлені різні модулі та вам потрібно використовувати певну установку python, спочатку, здається, shebang обмежений. Однак ви можете робити хитрощі, як показано нижче, щоб дозволити спочатку викликати шебанг як сценарій оболонки, а потім вибрати пітон. Це дуже гнучкий imo:

#!/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

Таким чином він буде працювати всюди (без ./ перед назвою файлу)


Я сумніваюся, що це найкраща практика, і я настійно рекомендую використовувати рішення GlassGhost .
colidyre

Я вважав це корисним, і воно прекрасно працювало для мене. це було добре пояснено. Я вдячний зауваженням, що вказують, чому це не найкраща практика. Я прагну вчитися.
Чарльз Кер’єр

0

Абсолютний проти логічного шляху:

Це справді питання про те, чи повинен шлях до інтерпретатора Python бути абсолютним або логічним ( /usr/bin/env) щодо переносимості.

Зустрічаючи інші відповіді на ці та інші сайтах Stack , які говорили про проблеми в загальному вигляді без підтримки доказів, я скоїв якийсь на насправді, дійсно , зернисте тестування & аналіз на цьому самому питання про unix.stackexchange.com . Замість того, щоб надіслати цю відповідь тут, я вкажу тих, хто цікавиться порівняльним аналізом, на цю відповідь:

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

Будучи інженером Linux, моя мета - завжди забезпечити найбільш підходящі, оптимізовані хости для своїх клієнтів-розробників, тому питання середовищ Python було чимось, на що я справді потребував ґрунтовної відповіді. Моя думка після тестування полягала в тому, що логічний шлях у she-bang був кращим із (2) варіантів.


-3

Використовуйте спочатку

which python

Це дасть вихід як місце, де присутній мій інтерпретатор пітонів (бінарний).

Цей вихід може бути будь-яким

/usr/bin/python

або

/bin/python

Тепер належним чином виберіть лінію shebang і використовуйте її.

Для узагальнення ми можемо використовувати:

#!/usr/bin/env

або

#!/bin/env

3
Це, швидше за все, не переноситься для інших систем. #!/usr/bin/envробить правильний вибір для вас.
фрагментарна

Ось чому ви використовуєте whichкоманду - вона поверне правильний рядок для вашої конкретної системи.
SDsolar

1
... а потім кожен раз, коли сценарій повинен бути виконаний на іншій машині, ви запускаєте which pythonзнову і змінюєте скрипт, якщо вихід відрізняється від поточного shebang
фрагментарнареальність

2
-1 Це найбільш крихке можливе рішення. Він гарантовано правильним лише для системи, на якій написано ваш скрипт python. Використовуйте #! / Usr / bin / env python3 для портативності
Myles Hollowed
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.