Чому Python в Linux потребує рядка #! / Usr / bin / python?


50

Досить просте запитання: чому в Linux, чому Python потрібен рядок?

#!/usr/bin/python

на початку файлу python, оскільки Windows ні?

Що це робить? Тому що опис "Посилання на Python" трохи розпливчастий ...


28
Нижче наведені відповіді правильні, жодна з них не відповідає тому, чому Windows не потребує цього рядка. Windows залежить від розширення файлу (частини після цього .), щоб визначити, що це за файл. Навіть Windows відходить від цього: вивчіть перші кілька рядків файлу Microsoft Word, і він констатує, що це насправді файл Microsoft Word.
Чарльз Грін

9
Слон в кімнаті полягає в тому, що НІКОЛИ не використовуйте / usr / bin / python, якщо ви не сумісні з python 2 та 3. Причина: арка посилає його на python3, рух, який визнає PSF, які рекомендують проти цього самі.
Ще один користувач

5
Це мається на увазі, але не вказано прямо у відповідях нижче, що це не потрібно . Це потрібно, якщо ви хочете виконати сценарій просто з власного імені ts. Ви завжди можете python myscript.pyзамість цього запустити .
Кріс Х

3
@CharlesGreen ми не можемо знати, чому Windows немає ;-) Це так.
Rinzwind

2
@YetAbodyUser Пройшло шість років і одинадцять місяців з моменту виходу Python 3, я вважаю, що людям було б краще дефолтом до 3 і чітко вказати використання 2, коли це необхідно.
JAB

Відповіді:


58

Python не має жодної такої особливої ​​вимоги до Linux. Це завантажувач програм на Unix / Linux, який використовує рядок "shebang", як його називають. Це насправді є особливістю, а не обмеженням, але ми дістанемося цього за мить. На сторінці Wiki на "shebang" є більше деталей, але я спробую дати огляд, а також порівняння з Windows тут.

Спочатку розглянемо ситуацію в Windows:

  • При спробі відкрити або запустити файл, Windows спочатку вивчає розширення цього файлу. Це остання частина назви файла, що починається з .файлів Python, як правило, це зазвичай .py.
  • Windows шукає, які дії вжити на основі розширення файлу.
    • Ця інформація записується в реєстр Windows; коли встановлено Python, він зазвичай повідомляє Windows, що .pyфайли слід відкривати за допомогою нещодавно встановленої програми Python (тобто інтерпретатора Python).
    • Кілька типів файлів мають вбудовану поведінку; наприклад, виконувані файли (наприклад, сам інтерпретатор Python) повинні закінчуватися .exe, а .batфайли виконуються як пакетні сценарії Windows.
    • Дія, зроблена для певного типу файлів, налаштовується . Ви можете, наприклад, сказати Windows, що замість запуску .pyфайлів python.exe, він повинен відкривати їх за допомогою іншої програми, наприклад текстового редактора notepad.exe.
      • У цьому випадку, щоб запустити скрипт Python, вам потрібно буде вручну зателефонувати python <scriptname>.py(або написати .batфайл, щоб зробити це за вас).

Тепер, що станеться , якщо є кубло лінія ( #!/usr/bin/pythonабо #!/usr/bin/env python) у верхній частині скрипта Python? Ну, оскільки #в Python є рядок коментарів, інтерпретатор Python просто ігнорує його. Це одна з причин, чому більшість мов сценаріїв, використовуваних у світі Unix / Linux, використовують #для запуску рядків коментарів.

Тож трохи оманливо сказати, що Windows "не потребує" #!рядку; Вікна не бачу в #!лінію, а насправді спирається на розширення файлу , щоб сказати йому , що робити. У цього є кілька недоліків:

  • Ви повинні назвати сценарії Python .pyу кінці, щоб автоматично їх розпізнавали як такі.
  • Немає простого способу відрізнити сценарії Python2 від скриптів Python3.
  • Як зазначалося раніше, якщо змінити поведінку запуску за замовчуванням для .pyтипу файлу, Windows більше не буде автоматично запускати ці сценарії з Python. Зауважте, що це можна зробити ненавмисно.

Тепер давайте розглянемо, як Unix / Linux запускає сценарії:

Перше, що слід зазначити, це те, що Unix / Linux, на відміну від Windows, не намагається "відкрити" сценарії Python за допомогою певної програми, принаймні концептуально; ОС знає, що скрипт - це те, що може бути виконано через щось, що називається "біт виконання" (що знаходиться поза межами цієї відповіді). Отже, якщо ви випадково наберете #!/usr/bin/pthonзамість цього #!/usr/bin/python, ви отримаєте повідомлення про помилку, що включає цей текст:

/usr/bin/pthon: bad interpreter: No such file or directory.

Слово "перекладач" дає нам уявлення про роль рядка shebang (хоча технічно зазначена програма може бути чимось іншим, ніж перекладач, наприклад, catабо редактор тексту). Коли ви намагаєтеся виконати файл, ось що відбувається:

  • Завантажувач програм Unix / Linux розглядає перші два байти цього файлу; якщо ці два байти є #!, то завантажувач інтерпретує решту рядка shebang (виключаючи сам shebang) як команду для запуску інтерпретатора, за допомогою якого запускати вміст файлу як сценарій.
  • Завантажувач програми запускає вказаний інтерпретатор, подаючи йому шлях вихідного файлу як аргумент.

Це має пару переваг:

  • Автор сценарію має більше контролю над тим, який інтерпретатор буде використовуватися (що вирішує питання Python2 / Python3), а іноді може передавати додатковий аргумент інтерпретатору (детальну інформацію див. На сторінці Wiki).
  • Ім'я сценарію ігнорується , тож ви можете називати сценарії Python все, що завгодно.

Зверніть увагу, нарешті, що Unix / Linux не потрібна лінія shebang для запуску сценарію Python. Нагадаємо, що насправді лише лінія shebang - це дозволяти завантажувачу програми вибрати перекладача. Але так само, як і в Windows, це можна зробити вручну:

python <myscript>

1
У Windows ви можете легко мати .py2та .py3розширення для сценаріїв Python 2 / Python 3. Отже, і Linux (+ x біт), і Windows (розширення файлу) потребують метаданих у файловій системі. Основна відмінність полягає в тому, що біт + x легше втрачається під час транзиту. Це не обов'язково є недоліком.
MSalters

1
@MSalters У біті виконання також закодовано набагато менше інформації. І зауважте, що у вас може бути кілька перекладачів Python2 в даній системі (у попередній моїй роботі була схожа ситуація з Ruby та іншими мовами); вирішення цього питання за допомогою лінії shebang майже тривіально, тоді як ситуація в Windows стає значно менш простежуваною, чим більше ви намагаєтеся керувати кількома подібними типами файлів.
Кайл Странд

Також, чи розширення насправді вважається "метаданими"? Це просто частина назви файлу.
Кайл Странд

1
Метадані файлу містять ціле ім'я файлу, час створення, біти доступу тощо. Замість цього мета замість метаданих - лише сам вміст. Що стосується "кількох перекладачів", то це справді справжня проблема, і саме тому вона не повинна бути в рядку shebang. Що робити , якщо у вас є /usr/bin/i686/pythonі /usr/bin/amd64/python? Ідеально розумно, але він порушує сценарії python, які мають жорстке кодування припущення /usr/bin/python. Вибір перекладача - це не вибір автора сценарію, а користувача сценарію. Сценарист повинен вибрати лише мову (діалект).
MSalters

1
@MSalters Ну, ось для чого /usr/bin/env, поряд із сценаріями налаштування env. Яка версія Windows для цього? Запуск regeditсценарію безпосередньо перед запуском .pyфайлу, щоб переконатися, що ви знайдете потрібного перекладача?
Кайл Странд

41

Рядок, який ви вказали, використовується для того, щоб вказати комп'ютеру, яку програму / інтерпретатор використовувати для прямого запуску файлу / сценарію, та будь-які аргументи, які слід передавати цій програмі під час запуску сценарію. Однак це не вимога Python , це вимога ядра / системи Linux, якщо ви маєте намір запустити сценарій безпосередньо (а не передати його Python синтаксисом нижче).

Він не потрібен, якщо ви збираєтесь виконати python script.pyабо подібне. Він потрібен лише в тому випадку, якщо ви маєте намір запустити сценарій / файл безпосередньо, не надаючи також інтерпретатора для використання (наприклад, python).


Для сценарію Bash він мав би щось подібне:

#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;

Це вказувало б системі, що при запуску вона повинна запускатися через /bin/bashяку є однією з мов оболонок / оболонок-скриптів у системі.


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

#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()

Це, як і для Bash, вказує на те, що його /usr/bin/pythonслід використовувати (це, мабуть, Python 2 або Python 3, залежно від вашої індивідуальної конфігурації системи).


Таким чином, ви можете запустити ./filename.pyабо ./executableабо ./scripttorunбезпосередньо.

Без цього рядка на початку, і якщо припустити, що ви встановили файл / сценарій виконуваним, і припускаючи, що ви працюєте зі сценарієм Python, вам доведеться запустити python filename.pyабо подібне, якби у вас не було #!/usr/bin/pythonрядка. (Для сценарію Bash, ви повинні зробити bash script.sh, або подібне для інших сценаріїв / мов, таких як Perl, Ruby тощо).

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


1
Цікава річ , щоб додати б , що можна вказати додаткові параметри після самого кубла, в більшості випадків так само, як якби перекладач був викликано безпосередньо ( #!/bin/bash -x, #!/usr/bin/perl -lanі т.д.).
kos

7
@kos: Я думаю, ви можете вказати саме один додатковий аргумент, який був PITA, коли один (слід) використовувати /usr/bin/env pythonдля отримання правильного пітона.
unperson325680

@progo Не впевнений, у чому проблема env, але, здається, проблема не в кількості аргументів: #!/usr/bin/perl -l -a -nмає три аргументи, але вона працює. Хоча знову ж таки, я не в змозі вирішити точну проблему.
kos

Коли явно викликає інтерпретатора зі скриптом як аргумент, немає жодної причини починати останнє ./. Іншими словами просто python filename.pyабо bash script.shбуде добре працювати. Єдина причина для включення ./- це ім'я команди, коли ви хочете сказати оболонці не здійснювати пошук $PATH(який, ймовірно, не знайде файли в поточному каталозі), а пройдуть шлях, який ви вказали як є. Але це не стосується аргументів команд.
Марк ван Левен

@kos: Проблема може полягати в тому, як envотримує решту аргументів від ядра. Усі вони могли вважатись одним із великих аргументів, не виконаних розбиттям по простору. Вибачте за артикуляцію, я вже не пам'ятаю деталей цього добре
unperson325680

16

Лінія:

#!/usr/bin/python

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

Таким чином, рядок #!/usr/bin/pythonвказує, що вміст файлу буде інтерпретований pythonдвійковим файлом, розташованим в /usr/bin/python.

Зауважте, що рядок shebang аналізується ядром, і тоді скрипт з часом буде викликаний як аргумент:

python script_name

Аналогічно у випадку #!/bin/bash:

bash script_name

2
Я не думаю, що я жодного разу бачив дефіс в shebang. Оскільки слово утворене від "хеш" та "баг", то ваш правопис не дуже зрозумілий, оскільки, схоже, це поєднання "вона" та "баг".
Кайл Странд

Ви можете назвати його hashbang( #= "хеш") або shebang( #= "різкий"), залежно від того, як ви називаєте #персонажа. Однак, shebangсправді , це більш часто. @KyleStrand
командир байтів

7

Технічно це не вимагає. Для цього потрібен шлях до середовища, де виконується ваш сценарій. Ваші майбутні сценарії було б краще включити / usr / bin / env, тоді вкажіть python. Це отримує ваш сценарій у середовищі python, незалежно від того, де встановлено python. Ви хочете зробити це з міркувань сумісності, ви не можете бути впевнені, що наступний чоловік, з яким ви поділитеся своїм кодом, матиме встановлений python в usr / bin / python, або що вони матимуть дозволи для цих системних файлів.

Ось аналогічне запитання щодо переповнення стека .

Як виглядає у вашому сценарії:

#!/usr/bin/env python

Я також бачу певне занепокоєння щодо того, як вказати python3. Ось як це зробити:

#!/usr/bin/env python3

5

В Linux Python може або не вимагає #!рядка (shebang). Це залежить від того, як обробляються коди Python, або виконуючи коди в інтерактивному режимі Python, або в сценарії Python.

Інтерактивний режим Python дозволяє користувачеві безпосередньо вводити та запускати коди Python, що не вимагає лінії shebang. Щоб запустити інтерактивний режим, відкрийте термінал і наберіть pythonдля Python 2.X або python3для Python 3.X.

$  python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

$  python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Сценарій Python дозволяє користувачеві писати та зберігати коди Python у простому текстовому файлі, а потім запускати коди пізніше. Це може вимагати або не вимагати лінії шебанга. Однак є дві відомі причини, коли для використання сценарію Python в Linux потрібна лінія shebang.

  1. запускати Python-коди у виконавчому скрипті, тобто визначає, як коди повинні бути запущені та використовуючи інтерпретатор;

  2. запускати коди Python стосовно певної версії Python, тобто виконувати коди, сумісні з Python 2.X або Python 3.X

Попрактикуйтесь із сценаріями Python

Нижче наведено список та вміст файлів, за допомогою яких я показував випадки, що #!(shebang) рядок потрібен чи не потрібен.

$  ls -ln *.py
-rw-rw-r-- 1 1000 1000  94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py

$  file *.py
hello1.py:  ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py:  Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py:  Python script, ASCII text executable
  • hello1.py містить лише вихідний код.

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
  • hello2.py містить вихідний код і рядок shebang.

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
    
  • hello2e.pyмістить те саме, що hello2.pyі виконано.

  • hello3.pyмістить те ж, що hello2.py, за винятком того, що він адаптований для запуску з Python 3 шляхом перейменування першого рядка в #!/usr/bin/env python3.

  • hello3e.pyмістить те саме, що hello3.pyі виконано.

  • hello3m.pyмістить те саме, що hello3.pyі зроблено виконуваним, за винятком збереженого з Write Unicode BOMопцією в текстовому редакторі, тобто на панелі миші.

Крім цього, користувачеві буде представлено два способи запуску сценаріїв Python. Обидва методи були продемонстровані, як показано нижче.

Спосіб 1: Запустіть програму Python

Нижче наведені команди та висновки під час запуску вихідного коду з Python 2 та Python 3.

$  python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Обидві версії Python змогли запустити сценарій успішно. Отже, рядок shebang не потрібен під час запуску сценарію Python через pythonабо python3команду.

Спосіб 2: Запустити як скрипт Python

Нижче наведені команди та вихідні дані при запуску вихідного коду з рядком shebang, пристосованим ні до Python 2, ні до Python 3, включаючи невиконані та виконувані регістри.

$  ./hello1.py
bash: ./hello1.py: Permission denied

$  ./hello2.py
bash: ./hello2.py: Permission denied

$  ./hello3.py
bash: ./hello3.py: Permission denied

$  ./hello2e.py 
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  ./hello3e.py 
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Перші три сценарії вийшли з ладу, оскільки ці сценарії не виконуються, незалежно від того, чи має рядок shebang чи ні (Про підтримку підтвердження див. Додатковий приклад нижче). Останні два сценарії мають рядок shebang і є виконуваним.

Мабуть, сценарій, який був виконаний виконуваним, по суті є марним без рядка shebang. Отже, рядок shebang необхідний, і сценарій повинен бути виконаним під час запуску кодів Python у виконаному сценарії.

Коли шебанг не працює

У моєму підготовленому і перевіреному прикладі, запуск hello3m.pyвиконуваного сценарію не вдалося і повернув помилку.

$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory

Це відоме обмеження, що шибанг не працює або стає недійсним. Коли файл зберігається як Unicode BOM (Byte Order Mark), він не буде працювати нормально як виконуваний скрипт Python.

Додатковий приклад

Цей додатковий приклад розглядається лише як підтверджуючий доказ. Користувач повинен уникати запуску цього прикладу, хоча результат нешкідливий.

Я створив ще один файл під назвою hello1e.py, який містить те саме, що hello1.pyі зроблений виконуваним. Запуск цього сценарію повернув синтаксичну помилку.

$  ./hello1e.py 
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'

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

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

sysФайл був ідентифікований як файл PostScript, без розширення файлу. Цей файл можна відкрити в засобі перегляду документів, тобто Evince, і файл фактично містив скріншот вікна, яке я натискав раніше. На мій досвід, файл може бути розміром декількох мегабайт.

Знову потрібен рядок shebang, і сценарій повинен бути виконаним під час запуску сценарію Python як виконуваного сценарію. Інакше сценарій не буде поводитись так, як описано вище.

Додаткові нотатки

Термін "зроблено виконуваним" або "повинен бути виконаним" відноситься до дозволу на запуск сценарію. Це робиться, запустивши chmod +x FILENAMEкоманду в Терміналі, або встановивши прапорець "Дозволити цей файл запускатися як програма" або щось подібне у вікні " Властивості" , в файловому менеджері.

Хоча інші існуючі відповіді охоплювали майже все, ця відповідь застосовувала інший підхід, використовуючи практичні приклади для пояснення питання. Синтаксис коду був написаний обережно, таким чином, щоб приклади могли бути запущені або з Python 2, або з Python 3, як є.

Коди Python були адаптовані за допомогою використання Python у Windows та використання Python на платформах Unix , з додатковим однорядним кодом всюдисущого "Привіт, світ!" програма.

Всі коди та команди були повністю перевірені і працюють у системі Xubuntu 14.04, в якій за замовчуванням встановлені Python 2.7 та Python 3.4.


4

Це означає, що коли цей файл виконаний, ваш комп'ютер знає виконати його з програмою /usr/bin/python, саме так ви розкажете його на іншій мові, наприклад, bash, де ви б робили #!/bin/bash. Це так, що ви можете просто запустити:

./[file-to-execute]

І він буде знати, з яким файлом його виконати, а не вам самим потрібно вказувати щось на кшталт:

python ./[file-to-execute].py

Часто #!прийнято називати шебангом або хрустким ударом .


2
Також хашбанг.
Naftuli Kay

1

Якщо у вас встановлено кілька версій Python, /usr/bin/envпереконайтеся, що використаний інтерпретатор є першим у вашому середовищі $PATH. Альтернативою буде твердий код чогось подібного #!/usr/bin/python;

У Unix виконуваний файл, призначений для інтерпретації, може вказувати, який інтерпретатор використовувати, маючи #!на початку першого рядка, за яким слід інтерпретатор (та будь-які прапори, які можуть знадобитися).

Це правило застосовується лише для системи на базі UNIX.


0

корисно для ОС на зразок Linux, де Python 2.x досі є стандартом, але більшість людей також завантажують 3.x.

2.x працюватиме за замовчуванням. Отже, мій 3.x код, я приставку #! / Usr / bin / env python3, щоб 3.x запустив код. Я навіть можу вказати на незначну версію (python 3.xyz), якщо я так вирішив мати бета-версії або просто трохи старші версії.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.