Коли я використовую shebang #!/usr/bin/env python
для запуску сценарію, як система знає, який python
використовувати? якщо я шукаю python
бін-шлях у змінних оточення, я нічого не знайду.
env | grep -i python
Коли я використовую shebang #!/usr/bin/env python
для запуску сценарію, як система знає, який python
використовувати? якщо я шукаю python
бін-шлях у змінних оточення, я нічого не знайду.
env | grep -i python
Відповіді:
Шебанг очікує, що повний шлях до інтерпретатора буде використаний, тому наступний синтаксис був би невірним:
#!python
Якщо встановити такий повний шлях, це може спрацювати:
#!/usr/local/bin/python
але було б не портативна , як пітон може бути встановлений /bin
, /opt/python/bin
або де -то інше місце.
Використання env
#!/usr/bin/env python
це метод, що дозволяє портативному способу вказати до ОС повний шлях, еквівалентний тому, де python
вперше знаходиться в PATH
.
Рядок shebang (від "різкого удару", тобто #!
) обробляється ядром. Ядро не хоче знати про такі змінні середовища, як PATH
. Отже, ім'я в рядку shebang має бути абсолютним шляхом до виконуваного файлу. Ви також можете вказати додатковий аргумент для передачі цього виконуваного файлу перед назвою скрипту (із системними обмеженнями я тут не заходжу). Наприклад, для сценарію Python можна вказати
#!/usr/bin/python
в першому рядку, і коли ви виконаєте сценарій, ядро насправді виконає /usr/bin/python /path/to/script
. Але це не зручно: потрібно вказати повний шлях команди. Що робити , якщо у вас є python
в /usr/bin
на деяких машинах і /usr/local/bin
на інших? Або ви хочете встановити PATH
для /home/joe/opt/python-2.5/bin
того, щоб використовувати конкретну версію Python? Оскільки ядро не виконає PATH
пошук для вас, ідея полягає в тому, щоб ядро запустило команду, яка по черзі шукає потрібного інтерпретатора в PATH
:
#!/fixed/path/to/path-lookup-command python
Це path-lookup-command
повинно взяти ім'я виконуваного файлу як аргумент, шукати його PATH
і виконувати: ядро запуститься /fixed/path/to/path-lookup-command python /path/to/script
. Як це відбувається, env
команда робить саме це. Його головне призначення - запустити команду з іншим середовищем, але оскільки вона шукає ім'я команди $PATH
, вона ідеально підходить для нашої мети тут.
Хоча це офіційно не гарантовано, історичні системи Unix при умови , env
в /usr/bin
, і сучасні системи зберегли це місце саме через широкого використання #!/usr/bin/env
. Отже, на практиці спосіб визначити, що сценарій повинен виконувати улюблений інтерпретатор Python користувача
#!/usr/bin/env python
env
і which
? оскільки з цього моменту ви отримаєте найбільш придатний для виконання файл з мого середовища PATH.
which
знаходить виконуваний файл і друкує його шлях. env
знаходить програму, задану першим аргументом, і виконує її, передаючи їй решта аргументів.
env
по which
суті є eval версія .
Правильно, так що запустіть:
env | grep PATH
Ваш $ PATH - це список каталогів. Unix буде проходити через цей список каталогів по порядку, поки не знайде "python".
Ви можете побачити, який каталог він знайде, за допомогою команди "який":
which python
sys.path
між активованими env $ env python3
( ['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/.local/lib/python3.4/site-packages', '/usr/lib/python3.4/site-packages', '/usr/local/lib/python3.4/dist-packages', '/usr/lib/python3/dist-packages']
) та ./env/bin/python3
(['', '/home/user/test', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-x86_64-linux-gnu', '/usr/lib/python3.4/lib-dynload', '/home/user/test/env3/lib/python3.4/site-packages']
).