Почему делает Python в Linux, требуют строки #!/usr/bin/python?

Довольно простой вопрос: В Linux, почему Python требует строки

#!/usr/bin/python

в начале файла Python, так как Windows не делает?

Что это делает? потому что описание "Ссылки на Python" немного неопределенно...

57
задан 10 November 2015 в 19:54

8 ответов

Python не имеет такого специального требования на Linux. Именно загрузчик программы на Unix/Linux использует строку "shebang", как она называется. На самом деле это скорее особенность, чем ограничение, но мы к этому подойдём через некоторое время. Вики-страница на "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 .py (или написать ). bat файл, чтобы сделать это за вас).

Что произойдёт, если в верхней части питоновского скрипта появится строка shebang (#!/usr/bin/python] или #!/usr/bin/env python)? Ну, так как # - это строка-комментарий на Python, интерпретатор Python просто игнорирует её. Это одна из причин, по которой большинство скриптовых языков, используемых в мире Unix/Linux, используют # для запуска строк-комментариев.

Так что немного ошибочно говорить, что Windows "не нужна" строка #!; 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>
    
69
ответ дан 22 November 2019 в 23:50

Строка:

#!/usr/bin/python

называется 'shebang' и указывает путь к двоичному файлу интерпретатора, который будет использоваться для интерпретации остальных команд в файле. Обычно это первая строка скрипта.

Итак, строка #!/usr/bin/python указывает, что содержимое файла будет интерпретироваться двоичным файлом python, расположенным по адресу /usr/bin/python.

Обратите внимание, что строка shebang анализируется ядром и в конце концов скрипт будет вызван как аргумент:

python script_name

Аналогично в случае #! /bin/bash:

bash script_name
16
ответ дан 22 November 2019 в 23:50

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

Вот похожий вопрос из переполнения стека.

Как это выглядит в вашем сценарии:

#!/usr/bin/env python

Я также вижу некоторую озабоченность по поводу того, как указать python3. Вот как это сделать:

#!/usr/bin/env python3
7
ответ дан 22 November 2019 в 23:50

Это значит, что когда этот файл выполняется, ваш компьютер знает, как выполнить его с помощью программы /usr/bin/python, так вы можете отличить его от другого языка, например, bash, где бы вы делали #!/bin/bash. Это для того, чтобы вы могли просто бежать:

./[file-to-execute]

И он будет знать, в каком файле его выполнять, а не вы сами должны указывать что-то вроде:

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

Часть #! обычно упоминается как shebang, crunch bang или hashbang.

4
ответ дан 22 November 2019 в 23:50

Если у вас установлено несколько версий Python, / usr / bin / env гарантирует, что используемый интерпретатор будет первым в $ PATH вашей среды . Альтернативой может быть жесткое кодирование чего-то вроде #! / Usr / bin / python ;

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

Это правило применимо только для систем на базе UNIX.

1
ответ дан 22 November 2019 в 23:50

Указанная вами строка используется для того, чтобы сообщить компьютеру, какую программу/интерпретатор использовать при прямом запуске файла/скрипта, и любые аргументы, которые должны быть переданы этой программе при выполнении скрипта. Однако, это не требование Python, это требование ядра/системы linux, если вы собираетесь выполнять скрипт напрямую (а не передавать его на Python по синтаксису, указанному ниже).

Это не нужно, если вы собираетесь выполнять python script.py или аналогичный скрипт. Он нужен только в том случае, если вы собираетесь запускать скрипт/файл напрямую, не предоставляя при этом интерпретатор для использования (например, python).


Для Bash-скрипта это будет иметь нечто подобное:

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

Это укажет системе, что когда он запускается, он должен быть запущен через /bin/bash, который является одним из оболочек/языков shell-скриптов в системе.


Для кода на 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, вам пришлось бы запустить py py или аналогичный файл, если бы у вас не было строки #!/usr/bin/python. (Для Bash скрипта, вы должны были бы сделать bash script.sh, или аналогичные для других скриптов/языков, таких как Perl, Ruby, и т.д.)

Подсветка синтаксиса выше является специфическим для каждого языка в каждом разделе, хотя это не имеет значения.

42
ответ дан 22 November 2019 в 23:50

В 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 в текстовом файле, а затем запустите коды позже. Это может потребовать, а может и не потребовать линию шебанг. Однако есть две известные причины, по которым строка shebang требуется для использования сценария Python в Linux.

  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 ("Привет от Python% s \ n"% (sys.version,))
    print ("Привет, мир!")
     
  • hello2.py содержит исходный код и строку shebang.

     #! / Usr / bin / env python
    import sys
    sys.stdout.write ("Привет от Python% s \ n"% (sys.version,))
    print ("Привет, мир!")
     
  • hello2e.py содержит то же, что и hello2.py , и является исполняемым.

  • hello3.py содержит то же, что и hello2.py , за исключением того, что адаптирован для работы с Python 3 путем переименования первой строки в #! / usr / bin / env python3 .

  • hello3e.py содержит то же, что и hello3.py и сделан исполняемым.

  • hello3m.py содержит то же, что и hello3.py , и сделан исполняемым, за исключением сохранения с опцией Записать спецификацию Unicode в текстовом редакторе, то есть Коврик для мыши.

] После этого пользователю будут представлены два метода для запуска скриптов 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 в исполняемом сценарии.

Когда shebang не работает

В моем подготовленном и протестированном примере выполняется hello3m.py ], поскольку исполняемый сценарий завершился неудачно и вернул ошибку.

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

Это известное ограничение , что shebang не работает или становится недействительным. Когда файл сохраняется как Unicode BOM (метка порядка байтов), он не сможет нормально работать как исполняемый сценарий 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 с дополнительным однострочным кодом вездесущего "Hello, World!"

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

5
ответ дан 22 November 2019 в 23:50

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

2.x запускается по умолчанию. Итак, мой код 3.x, я добавляю префикс

#!/usr/bin/env python3

, чтобы 3.x запускал код. Я могу даже указать, вплоть до незначительной версии (python 3.x.y.z), если я выберу бета-версии или только немного более старые версии.

0
ответ дан 22 November 2019 в 23:50

Другие вопросы по тегам:

Похожие вопросы: