Poniższa odpowiedź mówi, że jest to tylko wiersz komentarza. Nie zawsze tak jest. Mam „Witaj, świecie!” Skrypt CGI (.py), który będzie uruchamiał i wyświetlał stronę internetową tylko #!/usr/bin/env pythonu góry.
Odwiedziłem ten post tyle razy w ciągu 7 lat, ponieważ czasami zapominam hashbang env. Skopiuj makaron :)
BugHunterUK
Odpowiedzi:
1082
Jeśli masz zainstalowanych kilka wersji Pythona, /usr/bin/envupewnij się, że użyty interpreter będzie pierwszym w twoim środowisku $PATH. Alternatywą byłoby hardcode coś takiego #!/usr/bin/python; to jest ok, ale mniej elastyczne.
W Uniksie plik wykonywalny , który ma być interpretowany, może wskazywać, jakiego interpretera użyć, umieszczając #!na początku pierwszego wiersza, a za nim interpreter (i wszelkie potrzebne flagi).
Jeśli mówisz o innych platformach, oczywiście ta zasada nie ma zastosowania (ale ta „linia shebang” nie szkodzi i pomoże, jeśli kiedykolwiek skopiujesz ten skrypt na platformę z bazą Unix, taką jak Linux, Mac itp.).
Wystarczy dodać: dotyczy to uruchamiania go w systemie Unix poprzez uczynienie go wykonywalnym ( chmod +x myscript.py), a następnie uruchamianie bezpośrednio ./myscript.py:, a nie tylko python myscript.py.
Craig McQueen,
28
użycie envdaje maksymalną elastyczność, ponieważ użytkownik może wybrać tłumacza, który będzie używany, zmieniając ŚCIEŻKĘ. Często ta elastyczność nie jest wymagana, ale wadą jest to, że na przykład Linux nie może użyć nazwy skryptu dla nazwy procesu psi powraca do „python”. Na przykład przy pakowaniu aplikacji Pythona dla dystrybucji radzę nie używać env.
Ważne słowo ostrzeżenia, wartość zwracana env ostatecznie wygasa. Co raczej nie wpłynie na ciebie, jeśli prowadzisz krótkotrwałe procesy. Jednak /usr/bin/env: Key has expiredpo wielu godzinach proces umierał z tą wiadomością .
malaverdiere
4
@malaverdiere czy możesz połączyć się z jakimikolwiek zasobami, które wyjaśniają to zachowanie związane z wygaśnięciem? Nie mogę ich znaleźć.
W informatyce shebang (zwany również hashbangiem, hashplingiem, funtem lub crunchbangiem) odnosi się do znaków „#!” gdy są to pierwsze dwa znaki w dyrektywie interpretera jako pierwsza linia pliku tekstowego. W systemie operacyjnym uniksopodobnym moduł ładujący pobiera obecność tych dwóch znaków jako wskazanie, że plik jest skryptem, i próbuje wykonać ten skrypt za pomocą interpretera określonego przez resztę pierwszego wiersza pliku.
Nawet w systemie Windows, w którym linia shebang nie określa uruchomionego interpretera, można przekazać opcje do interpretera, określając je w linii shebang. Uważam, że przydatne jest utrzymywanie ogólnej linii shebang w jednorazowych skryptach (takich jak te, które piszę, odpowiadając na pytania dotyczące SO), dzięki czemu mogę szybko przetestować je zarówno w systemie Windows, jak i ArchLinux .
Narzędzie env pozwala na wywołanie polecenia na ścieżce:
Pierwszy pozostały argument określa nazwę programu do wywołania; jest wyszukiwane zgodnie ze PATHzmienną środowiskową. Wszelkie pozostałe argumenty są przekazywane jako argumenty do tego programu.
Łatwy do znalezienia w Google - jeśli ktoś zna słowa kluczowe (niezbędna jest „linia shebang”).
Arafangion
14
W rzeczywistości to wyjaśnienie jest jaśniejsze niż w przypadku innych referencji sprawdzonych przez Google. Zawsze lepiej jest uzyskać wyjaśnienie 1 akapitu ukierunkowane na pytanie, niż przeczytać całą instrukcję dotyczącą każdego potencjalnego zastosowania.
@ulidtko: Ciekawa wyszukiwarka, zastanów się nad napisaniem odpowiedzi, aby pytanie Johna Garciasa miało lepszą odpowiedź.
Arafangion,
1
„Nawet w systemie Windows, w którym linia shebang nie określa uruchomionego interpretera, możesz przekazać opcje tłumaczowi, określając je w linii shebang”. To jest po prostu fałsz; jeśli coś takiego się zdarzy, to dlatego, że sam tłumacz przetwarza linię shebang. Jeśli tłumacz nie ma specjalnego rozpoznania dla linii shebang, nic takiego się nie dzieje. Windows nic nie robi z liniami shebang. ”W tym przypadku możesz opisać program uruchamiający python: python.org/dev/peps/pep-0397 .
Kaz
154
Rozwijając nieco inne odpowiedzi, oto mały przykład tego, jak skrypty wiersza poleceń mogą wpaść w kłopoty przez nieumyślne użycie /usr/bin/envlinii shebang:
Jednym ze sposobów ochrony przed tego rodzaju problemami jest użycie wersjonowanych nazw poleceń python, które są zwykle instalowane z większością Pythonów:
Różnica między lokalną a globalną. Jeśli which pythonwróci /usr/bin/python, lokalna ścieżka do katalogu może być ciężko kodowane: #!/usr/bin/python. Ale jest to mniej elastyczne niż #!/usr/bin/env pythonma to zastosowanie globalne.
noobninja
85
Aby uruchomić skrypt Pythona, musimy powiedzieć powłoce trzy rzeczy:
Że plik jest skryptem
Który interpreter chcemy wykonać skrypt
Ścieżka wspomnianego tłumacza
Shebang #!wykonuje (1.). Shebang zaczyna się od, #ponieważ #znak jest znacznikiem komentarza w wielu językach skryptowych. Treść linii shebang jest zatem automatycznie ignorowana przez tłumacza.
W envrealizuje polecenie (2) i (3). Cytując „grawitację”,
Typowym zastosowaniem tego envpolecenia jest uruchamianie interpreterów, wykorzystując fakt, że env przeszuka $ PATH dla polecenia, które ma zostać uruchomione. Ponieważ linia shebang wymaga podania bezwzględnej ścieżki, a lokalizacja różnych interpretatorów (perl, bash, python) może się bardzo różnić, często używa się:
#!/usr/bin/env perl zamiast zgadywać, czy jest to / bin / perl, / usr / bin / perl, / usr / local / bin / perl, / usr / local / pkg / perl, / fileserver / usr / bin / perl lub / home / MrDaniel / usr / bin / perl w systemie użytkownika ...
Z drugiej strony, env prawie zawsze znajduje się w / usr / bin / env. (Z wyjątkiem przypadków, gdy tak nie jest; niektóre systemy mogą używać / bin / env, ale jest to dość rzadka okazja i zdarza się tylko w systemach innych niż Linux).
W ogóle nie potrzebujesz tej linii. System wywoła Python, a następnie interpreter Pythona uruchomi skrypt.
Ale jeśli zamierzasz użyć: $./myscript.py
Wywołując go bezpośrednio jak zwykły program lub skrypt bash, musisz napisać ten wiersz, aby określić w systemie, którego programu użyć, aby go uruchomić (a także umożliwić wykonanie go za pomocą chmod 755)
Jeśli porównanie jest prawdziwe, reszta linii jest analizowana przez jądro Linuksa, które wykonuje kolejne execwywołanie ze ścieżką /usr/bin/env pythoni bieżącym plikiem jako pierwszym argumentem:
/usr/bin/env python /path/to/script.py
i działa to na każdy język skryptowy, który używa #jako znaku komentarza.
I tak, możesz wykonać nieskończoną pętlę za pomocą:
printf '#!/a\n'| sudo tee /a
sudo chmod +x /a
/a
Bash rozpoznaje błąd:
-bash:/a: /a: bad interpreter:Too many levels of symbolic links
#! akurat jest czytelny dla ludzi, ale nie jest to wymagane.
Jeśli plik zaczął się od różnych bajtów, execwywołanie systemowe użyłoby innej procedury obsługi. Innym najważniejszym wbudowanym modułem obsługi są pliki wykonywalne ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, który sprawdza bajty 7f 45 4c 46(które również są ludźmi) czytelne dla .ELF). Potwierdźmy to, czytając 4 pierwsze bajty /bin/ls, czyli plik wykonywalny ELF:
Nie sądzę jednak, że POSIX określa shebangs: https://unix.stackexchange.com/a/346214/32558 , chociaż wspomina o tym w sekcjach uzasadnienia oraz w formie „jeśli skrypty wykonywalne są obsługiwane przez system, coś może zdarzyć". Wydaje się jednak, że macOS i FreeBSD go implementują.
PATH motywacja do wyszukiwania
Prawdopodobnie jedną z głównych motywów istnienia shebangów jest fakt, że w Linuksie często chcemy uruchamiać polecenia z PATH:
basename-of-command
zamiast:
/full/path/to/basename-of-command
Ale bez mechanizmu shebang skąd Linux wiedziałby, jak uruchomić każdy typ pliku?
Kodowanie rozszerzenia w poleceniach:
basename-of-command.py
lub wdrożenie wyszukiwania PATH na każdym tłumaczu:
python basename-of-command
byłaby możliwa, ale to ma główny problem, że wszystko się psuje, jeśli kiedykolwiek zdecydujemy się zmienić polecenie na inny język.
Technicznie rzecz biorąc, w Pythonie jest to tylko wiersz komentarza.
Ten wiersz jest używany tylko wtedy, gdy uruchomisz skrypt py z powłoki (z wiersza poleceń). Nazywa się to „ Shebang !” i jest używany w różnych sytuacjach, nie tylko ze skryptami Python.
Tutaj instruuje powłokę, aby uruchomiła określoną wersję Pythona (aby zająć się resztą pliku.
Shebang to koncepcja uniksowa. Warto wspomnieć, że działa również w systemie Windows, jeśli masz zainstalowany program uruchamiający Pythonpy.exe . Jest to część standardowej instalacji Pythona.
florisla
38
Głównym powodem tego jest uczynienie skryptu przenośnym w środowiskach systemu operacyjnego.
Na przykład w mingw skrypty python używają:
#!/c/python3k/python
a w dystrybucji GNU / Linux jest to albo:
#!/usr/local/bin/python
lub
#!/usr/bin/python
w ramach najlepszego komercyjnego systemu Uni / SW ze wszystkich (OS / X) jest to:
#!/Applications/MacPython 2.5/python
lub na FreeBSD:
#!/usr/local/bin/python
Jednak wszystkie te różnice mogą sprawić, że skrypt będzie przenośny we wszystkich przy użyciu:
Pod MacOSX tak też jest /usr/bin/python. Pod Linuksem Python zainstalowany przez system jest również prawie na pewno /usr/bin/python(nigdy nie widziałem nic innego i nie miałoby to sensu). Pamiętaj, że mogą istnieć systemy, które nie mają /usr/bin/env.
Albert,
1
Jeśli korzystasz z OSX i korzystasz z Homebrew i postępujesz zgodnie z domyślnymi instrukcjami instalacji, będzie on pod #! / Usr / local / bin / python
będzie
@ Jean-PaulCalderone: Zobacz odpowiedź saaj poniżej.
pydsigner
Aktualizacja na rok 2018: Bare pythonnie jest tak przenośny, to domyślny interpreter Pythona w dystrybucji. Arch Linux domyślnie
używa
22
Prawdopodobnie sensowne jest podkreślenie jednej rzeczy, której większość przeoczyła, co może uniemożliwić natychmiastowe zrozumienie. Kiedy piszeszpython w terminalu zwykle nie podajesz pełnej ścieżki. Zamiast tego plik wykonywalny jest sprawdzany w PATHzmiennej środowiskowej. Z kolei, jeśli chcesz bezpośrednio uruchomić program w języku Python /path/to/app.py, musisz powiedzieć powłoce, jakiego interpretera ma użyć (za pomocą skrótu , co inni współautorzy wyjaśniają powyżej).
Hashbang oczekuje pełnej ścieżki do tłumacza. Aby więc bezpośrednio uruchomić program w języku Python, musisz podać pełną ścieżkę do pliku binarnego w języku Python, który różni się znacznie, szczególnie biorąc pod uwagę użycie virtualenv . Aby rozwiązać problem przenośności, zastosowano sztuczkę /usr/bin/env. Ten ostatni ma pierwotnie na celu zmianę środowiska w miejscu i uruchomienie w nim polecenia. Jeśli nie wprowadzono żadnych zmian, uruchamia polecenie w bieżącym środowisku, co skutecznie skutkuje tym samym PATHwyszukiwaniem, które załatwia sprawę .
Określa tylko jakiego interpretera chcesz użyć. Aby to zrozumieć, utwórz plik przez terminal, wykonując touch test.py, a następnie wpisz w tym pliku następujące czynności:
#!/usr/bin/env python3print"test"
i zrobić, chmod +x test.pyaby skrypt był wykonywalny. Po tym ./test.pypowinieneś otrzymać komunikat o błędzie:
File"./test.py", line 2print"test"^SyntaxError:Missing parentheses in call to 'print'
ponieważ python3 nie obsługuje operatora drukowania.
Teraz idź dalej i zmień pierwszą linię kodu na:
#!/usr/bin/env python2
i będzie działać, drukując testna standardowe wyjście, ponieważ python2 obsługuje operator drukowania. Teraz nauczyłeś się przełączać między interpretatorami skryptów.
Wydaje mi się, że pliki działają tak samo bez tej linii.
Jeśli tak, to może używasz programu Python w systemie Windows? Windows nie używa tej linii - zamiast tego używa rozszerzenia nazwy pliku do uruchomienia programu skojarzonego z tym rozszerzeniem.
Jednak w 2011 r. Opracowano „program uruchamiający w języku Python”, który (do pewnego stopnia) naśladuje zachowanie systemu Linux w systemie Windows. Jest to ograniczone tylko do wyboru, który interpreter Pythona ma być uruchomiony - np. Do wyboru między Pythonem 2 a Pythonem 3 w systemie, w którym oba są zainstalowane. Program uruchamiający jest opcjonalnie instalowany jak py.exepodczas instalacji w języku Python i może być powiązany z .pyplikami, dzięki czemu program uruchamiający sprawdzi tę linię, a następnie uruchomi określoną wersję interpretera języka Python.
Popełniłem błąd, nie mając linii i użyłem python script.py, i pewnego dnia po prostu zrobiłem ./myscript.py i wszystko przestało działać, a potem zdałem sobie sprawę, że system szuka pliku jako skryptu powłoki zamiast skryptu python.
Guagua
8
Jest to bardziej informacja historyczna niż „prawdziwa” odpowiedź.
Pamiętaj, że w dawnych czasach pan miał wiele systemów operacyjnych UNIX jak projektanci, których wszyscy mieli swoje własne pojęcie gdzie umieścić rzeczy, a czasami nie obejmują Python, Perl, Bash, lub wiele innych GNU / Open Source rzeczy w ogóle .
Dotyczyło to nawet różnych dystrybucji Linuksa. W systemie Linux - wcześniejszym niż FHS [1] - możesz mieć Pythona w / usr / bin / lub / usr / local / bin /. Lub może nie został zainstalowany, więc zbudowałeś swój własny i umieściłeś go w ~ / bin
Solaris był najgorszy, na jakim kiedykolwiek pracowałem, częściowo jako przejście z Berkeley Unix na System V. Możesz skończyć z rzeczami w / usr /, / usr / local /, / usr / ucb, / opt / itp. To może sprawić, że dla niektórych naprawdę długich ścieżek. Mam wspomnienia z Sunfreeware.com instalującego każdy pakiet we własnym katalogu, ale nie mogę sobie przypomnieć, czy to dowiązało pliki binarne do / usr / bin, czy nie.
Aha, a czasami / usr / bin był na serwerze NFS [2].
Więc envnarzędzie zostało opracowane, aby obejść ten problem.
Potem można było pisać #!/bin/env interpreteri tak długo, jak ścieżka była właściwa, istniała rozsądna szansa na bieg. Oczywiście rozsądne oznaczenie (dla Pythona i Perla), że ustawiłeś także odpowiednie zmienne środowiskowe. W przypadku bash / ksh / zsh to po prostu działało.
Było to ważne, ponieważ ludzie przekazywali skrypty powłoki (takie jak Perl i Python), a jeśli na stałe zapisałeś / usr / bin / python na stacji roboczej Red Hat Linux, zepsuje się na SGI ... no cóż, nie , Myślę, że IRIX umieścił pytona we właściwym miejscu. Ale na stacji Sparc może wcale nie działać.
Tęsknię za moją stacją Sparc. Ale nie za dużo. Ok, teraz masz mnie trollującego po E-Bay. Bastages
Jeśli uruchamiasz skrypt w środowisku wirtualnym, powiedzmy venv, wykonanie go which pythonpodczas pracy venvwyświetli ścieżkę do interpretera Pythona:
~/Envs/venv/bin/python
Zauważ, że nazwa środowiska wirtualnego jest osadzona w ścieżce do interpretera Pythona. Dlatego też zakodowanie tej ścieżki w skrypcie spowoduje dwa problemy:
Jeśli prześlesz skrypt do repozytorium, zmusisz innych użytkowników do posiadania tej samej nazwy środowiska wirtualnego . Dzieje się tak, jeśli najpierw zidentyfikują problem.
Nie będzie można uruchomić skryptu w wielu środowiskach wirtualnych, nawet jeśli wszystkie wymagane pakiety były dostępne w innych środowiskach wirtualnych.
Dlatego, aby dodać odpowiedź Jonathana , idealnym shebang jest #!/usr/bin/env pythonnie tylko przenośność w różnych systemach operacyjnych, ale także przenośność w środowiskach wirtualnych!
Biorąc pod uwagę problemy związane z przenośnością między python2i python3, zawsze należy określić jedną z wersji, chyba że program jest zgodny z obydwoma.
Niektóre dystrybucje pythonwysyłane są python3przez jakiś czas z linkami - nie polegaj na pythonbyciu python2.
Aby tolerować różnice między platformami, cały nowy kod, który musi wywoływać interpreter Pythona, nie powinien określać Pythona, a raczej python2 lub python3 (lub bardziej szczegółowe wersje python2.x i python3.x; zobacz uwagi dotyczące migracji ) . Tego rozróżnienia należy dokonać w shebangach, podczas wywoływania ze skryptu powłoki, podczas wywoływania za pomocą wywołania system () lub przy każdym innym kontekście.
Pozwala wybrać plik wykonywalny, którego chcesz użyć; co jest bardzo przydatne, jeśli być może masz wiele instalacji Pythona i różne moduły w każdym i chcesz wybrać. na przykład
#!/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 $ALTERNATIVE_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())
#!/usr/bin/env python
u góry.Odpowiedzi:
Jeśli masz zainstalowanych kilka wersji Pythona,
/usr/bin/env
upewnij się, że użyty interpreter będzie pierwszym w twoim środowisku$PATH
. Alternatywą byłoby hardcode coś takiego#!/usr/bin/python
; to jest ok, ale mniej elastyczne.W Uniksie plik wykonywalny , który ma być interpretowany, może wskazywać, jakiego interpretera użyć, umieszczając
#!
na początku pierwszego wiersza, a za nim interpreter (i wszelkie potrzebne flagi).Jeśli mówisz o innych platformach, oczywiście ta zasada nie ma zastosowania (ale ta „linia shebang” nie szkodzi i pomoże, jeśli kiedykolwiek skopiujesz ten skrypt na platformę z bazą Unix, taką jak Linux, Mac itp.).
źródło
chmod +x myscript.py
), a następnie uruchamianie bezpośrednio./myscript.py
:, a nie tylkopython myscript.py
.env
daje maksymalną elastyczność, ponieważ użytkownik może wybrać tłumacza, który będzie używany, zmieniając ŚCIEŻKĘ. Często ta elastyczność nie jest wymagana, ale wadą jest to, że na przykład Linux nie może użyć nazwy skryptu dla nazwy procesups
i powraca do „python”. Na przykład przy pakowaniu aplikacji Pythona dla dystrybucji radzę nie używaćenv
.py
program uruchamiający może korzystać z linii shebang w systemie Windows. Jest zawarty w Pythonie 3.3 lub można go zainstalować niezależnie ./usr/bin/env: Key has expired
po wielu godzinach proces umierał z tą wiadomością .To się nazywa linia shebang . Jak wyjaśnia wpis w Wikipedii :
Zobacz także wpis FAQ Unix .
Nawet w systemie Windows, w którym linia shebang nie określa uruchomionego interpretera, można przekazać opcje do interpretera, określając je w linii shebang. Uważam, że przydatne jest utrzymywanie ogólnej linii shebang w jednorazowych skryptach (takich jak te, które piszę, odpowiadając na pytania dotyczące SO), dzięki czemu mogę szybko przetestować je zarówno w systemie Windows, jak i ArchLinux .
Narzędzie env pozwala na wywołanie polecenia na ścieżce:
źródło
Rozwijając nieco inne odpowiedzi, oto mały przykład tego, jak skrypty wiersza poleceń mogą wpaść w kłopoty przez nieumyślne użycie
/usr/bin/env
linii shebang:Moduł json nie istnieje w Pythonie 2.5.
Jednym ze sposobów ochrony przed tego rodzaju problemami jest użycie wersjonowanych nazw poleceń python, które są zwykle instalowane z większością Pythonów:
Jeśli potrzebujesz tylko odróżnić Python 2.x i Python 3.x, najnowsze wydania Python 3 również zawierają
python3
nazwę:źródło
which python
wróci/usr/bin/python
, lokalna ścieżka do katalogu może być ciężko kodowane:#!/usr/bin/python
. Ale jest to mniej elastyczne niż#!/usr/bin/env python
ma to zastosowanie globalne.Aby uruchomić skrypt Pythona, musimy powiedzieć powłoce trzy rzeczy:
Shebang
#!
wykonuje (1.). Shebang zaczyna się od,#
ponieważ#
znak jest znacznikiem komentarza w wielu językach skryptowych. Treść linii shebang jest zatem automatycznie ignorowana przez tłumacza.W
env
realizuje polecenie (2) i (3). Cytując „grawitację”,źródło
Być może twoje pytanie brzmi w tym sensie:
Jeśli chcesz użyć:
$python myscript.py
W ogóle nie potrzebujesz tej linii. System wywoła Python, a następnie interpreter Pythona uruchomi skrypt.
Ale jeśli zamierzasz użyć:
$./myscript.py
Wywołując go bezpośrednio jak zwykły program lub skrypt bash, musisz napisać ten wiersz, aby określić w systemie, którego programu użyć, aby go uruchomić (a także umożliwić wykonanie go za pomocą
chmod 755
)źródło
exec
Wywołanie systemowe jądra Linux rozumie shebangs (#!
) natywnieKiedy robisz na bash:
w Linuksie wywołuje to wywołanie
exec
systemowe ze ścieżką./something
.Ta linia jądra zostaje wywołana w pliku przekazanym do
exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25Odczytuje pierwsze bajty pliku i porównuje je
#!
.Jeśli porównanie jest prawdziwe, reszta linii jest analizowana przez jądro Linuksa, które wykonuje kolejne
exec
wywołanie ze ścieżką/usr/bin/env python
i bieżącym plikiem jako pierwszym argumentem:i działa to na każdy język skryptowy, który używa
#
jako znaku komentarza.I tak, możesz wykonać nieskończoną pętlę za pomocą:
Bash rozpoznaje błąd:
#!
akurat jest czytelny dla ludzi, ale nie jest to wymagane.Jeśli plik zaczął się od różnych bajtów,
exec
wywołanie systemowe użyłoby innej procedury obsługi. Innym najważniejszym wbudowanym modułem obsługi są pliki wykonywalne ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, który sprawdza bajty7f 45 4c 46
(które również są ludźmi) czytelne dla.ELF
). Potwierdźmy to, czytając 4 pierwsze bajty/bin/ls
, czyli plik wykonywalny ELF:wynik:
Więc kiedy jądro zobaczy te bajty, pobiera plik ELF, poprawnie zapisuje go w pamięci i rozpoczyna z nim nowy proces. Zobacz także: W jaki sposób jądro uzyskuje wykonywalny plik binarny działający pod Linuksem?
Na koniec możesz dodać własne
binfmt_misc
mechanizmy shebang za pomocą mechanizmu. Na przykład możesz dodać niestandardowy moduł obsługi.jar
plików . Ten mechanizm obsługuje nawet programy obsługi według rozszerzeń plików. Inną aplikacją jest przezroczyste uruchamianie plików wykonywalnych o innej architekturze za pomocą QEMU .Nie sądzę jednak, że POSIX określa shebangs: https://unix.stackexchange.com/a/346214/32558 , chociaż wspomina o tym w sekcjach uzasadnienia oraz w formie „jeśli skrypty wykonywalne są obsługiwane przez system, coś może zdarzyć". Wydaje się jednak, że macOS i FreeBSD go implementują.
PATH
motywacja do wyszukiwaniaPrawdopodobnie jedną z głównych motywów istnienia shebangów jest fakt, że w Linuksie często chcemy uruchamiać polecenia z
PATH
:zamiast:
Ale bez mechanizmu shebang skąd Linux wiedziałby, jak uruchomić każdy typ pliku?
Kodowanie rozszerzenia w poleceniach:
lub wdrożenie wyszukiwania PATH na każdym tłumaczu:
byłaby możliwa, ale to ma główny problem, że wszystko się psuje, jeśli kiedykolwiek zdecydujemy się zmienić polecenie na inny język.
Shebangi pięknie rozwiązują ten problem.
źródło
Technicznie rzecz biorąc, w Pythonie jest to tylko wiersz komentarza.
Ten wiersz jest używany tylko wtedy, gdy uruchomisz skrypt py z powłoki (z wiersza poleceń). Nazywa się to „ Shebang !” i jest używany w różnych sytuacjach, nie tylko ze skryptami Python.
Tutaj instruuje powłokę, aby uruchomiła określoną wersję Pythona (aby zająć się resztą pliku.
źródło
py.exe
. Jest to część standardowej instalacji Pythona.Głównym powodem tego jest uczynienie skryptu przenośnym w środowiskach systemu operacyjnego.
Na przykład w mingw skrypty python używają:
a w dystrybucji GNU / Linux jest to albo:
lub
w ramach najlepszego komercyjnego systemu Uni / SW ze wszystkich (OS / X) jest to:
lub na FreeBSD:
Jednak wszystkie te różnice mogą sprawić, że skrypt będzie przenośny we wszystkich przy użyciu:
źródło
/usr/bin/python
. Pod Linuksem Python zainstalowany przez system jest również prawie na pewno/usr/bin/python
(nigdy nie widziałem nic innego i nie miałoby to sensu). Pamiętaj, że mogą istnieć systemy, które nie mają/usr/bin/env
.python
nie jest tak przenośny, to domyślny interpreter Pythona w dystrybucji. Arch Linux domyślniePrawdopodobnie sensowne jest podkreślenie jednej rzeczy, której większość przeoczyła, co może uniemożliwić natychmiastowe zrozumienie. Kiedy piszesz
python
w terminalu zwykle nie podajesz pełnej ścieżki. Zamiast tego plik wykonywalny jest sprawdzany wPATH
zmiennej środowiskowej. Z kolei, jeśli chcesz bezpośrednio uruchomić program w języku Python/path/to/app.py
, musisz powiedzieć powłoce, jakiego interpretera ma użyć (za pomocą skrótu , co inni współautorzy wyjaśniają powyżej).Hashbang oczekuje pełnej ścieżki do tłumacza. Aby więc bezpośrednio uruchomić program w języku Python, musisz podać pełną ścieżkę do pliku binarnego w języku Python, który różni się znacznie, szczególnie biorąc pod uwagę użycie virtualenv . Aby rozwiązać problem przenośności, zastosowano sztuczkę
/usr/bin/env
. Ten ostatni ma pierwotnie na celu zmianę środowiska w miejscu i uruchomienie w nim polecenia. Jeśli nie wprowadzono żadnych zmian, uruchamia polecenie w bieżącym środowisku, co skutecznie skutkuje tym samymPATH
wyszukiwaniem, które załatwia sprawę .Źródło z unix stackexchange
źródło
Jest to konwencja powłoki, która informuje powłokę, który program może wykonać skrypt.
rozwiązuje ścieżkę do pliku binarnego Python.
źródło
Jest to zalecany sposób zaproponowany w dokumentacji:
z http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
źródło
Możesz spróbować rozwiązać ten problem, używając virtualenv
Oto test.py
Twórz środowiska wirtualne
aktywuj każde środowisko, a następnie sprawdź różnice
źródło
Określa tylko jakiego interpretera chcesz użyć. Aby to zrozumieć, utwórz plik przez terminal, wykonując
touch test.py
, a następnie wpisz w tym pliku następujące czynności:i zrobić,
chmod +x test.py
aby skrypt był wykonywalny. Po tym./test.py
powinieneś otrzymać komunikat o błędzie:ponieważ python3 nie obsługuje operatora drukowania.
Teraz idź dalej i zmień pierwszą linię kodu na:
i będzie działać, drukując
test
na standardowe wyjście, ponieważ python2 obsługuje operator drukowania. Teraz nauczyłeś się przełączać między interpretatorami skryptów.źródło
Jeśli tak, to może używasz programu Python w systemie Windows? Windows nie używa tej linii - zamiast tego używa rozszerzenia nazwy pliku do uruchomienia programu skojarzonego z tym rozszerzeniem.
Jednak w 2011 r. Opracowano „program uruchamiający w języku Python”, który (do pewnego stopnia) naśladuje zachowanie systemu Linux w systemie Windows. Jest to ograniczone tylko do wyboru, który interpreter Pythona ma być uruchomiony - np. Do wyboru między Pythonem 2 a Pythonem 3 w systemie, w którym oba są zainstalowane. Program uruchamiający jest opcjonalnie instalowany jak
py.exe
podczas instalacji w języku Python i może być powiązany z.py
plikami, dzięki czemu program uruchamiający sprawdzi tę linię, a następnie uruchomi określoną wersję interpretera języka Python.źródło
$ python myscript.py
.Jest to bardziej informacja historyczna niż „prawdziwa” odpowiedź.
Pamiętaj, że w dawnych czasach pan miał wiele systemów operacyjnych UNIX jak projektanci, których wszyscy mieli swoje własne pojęcie gdzie umieścić rzeczy, a czasami nie obejmują Python, Perl, Bash, lub wiele innych GNU / Open Source rzeczy w ogóle .
Dotyczyło to nawet różnych dystrybucji Linuksa. W systemie Linux - wcześniejszym niż FHS [1] - możesz mieć Pythona w / usr / bin / lub / usr / local / bin /. Lub może nie został zainstalowany, więc zbudowałeś swój własny i umieściłeś go w ~ / bin
Solaris był najgorszy, na jakim kiedykolwiek pracowałem, częściowo jako przejście z Berkeley Unix na System V. Możesz skończyć z rzeczami w / usr /, / usr / local /, / usr / ucb, / opt / itp. To może sprawić, że dla niektórych naprawdę długich ścieżek. Mam wspomnienia z Sunfreeware.com instalującego każdy pakiet we własnym katalogu, ale nie mogę sobie przypomnieć, czy to dowiązało pliki binarne do / usr / bin, czy nie.
Aha, a czasami / usr / bin był na serwerze NFS [2].
Więc
env
narzędzie zostało opracowane, aby obejść ten problem.Potem można było pisać
#!/bin/env interpreter
i tak długo, jak ścieżka była właściwa, istniała rozsądna szansa na bieg. Oczywiście rozsądne oznaczenie (dla Pythona i Perla), że ustawiłeś także odpowiednie zmienne środowiskowe. W przypadku bash / ksh / zsh to po prostu działało.Było to ważne, ponieważ ludzie przekazywali skrypty powłoki (takie jak Perl i Python), a jeśli na stałe zapisałeś / usr / bin / python na stacji roboczej Red Hat Linux, zepsuje się na SGI ... no cóż, nie , Myślę, że IRIX umieścił pytona we właściwym miejscu. Ale na stacji Sparc może wcale nie działać.
Tęsknię za moją stacją Sparc. Ale nie za dużo. Ok, teraz masz mnie trollującego po E-Bay. Bastages
[1] Standard hierarchii systemu plików. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] Tak, a czasem ludzie nadal robią takie rzeczy. I nie, nie miałem na pasku ani rzepy, ani cebuli.
źródło
Jeśli uruchamiasz skrypt w środowisku wirtualnym, powiedzmy
venv
, wykonanie gowhich python
podczas pracyvenv
wyświetli ścieżkę do interpretera Pythona:~/Envs/venv/bin/python
Zauważ, że nazwa środowiska wirtualnego jest osadzona w ścieżce do interpretera Pythona. Dlatego też zakodowanie tej ścieżki w skrypcie spowoduje dwa problemy:
Dlatego, aby dodać odpowiedź Jonathana , idealnym shebang jest
#!/usr/bin/env python
nie tylko przenośność w różnych systemach operacyjnych, ale także przenośność w środowiskach wirtualnych!źródło
Biorąc pod uwagę problemy związane z przenośnością między
python2
ipython3
, zawsze należy określić jedną z wersji, chyba że program jest zgodny z obydwoma.Niektóre dystrybucje
python
wysyłane sąpython3
przez jakiś czas z linkami - nie polegaj napython
byciupython2
.Podkreśla to PEP 394 :
źródło
Mówi interpreterowi, z którą wersją Pythona uruchomić program, gdy masz wiele wersji Pythona.
źródło
Pozwala wybrać plik wykonywalny, którego chcesz użyć; co jest bardzo przydatne, jeśli być może masz wiele instalacji Pythona i różne moduły w każdym i chcesz wybrać. na przykład
źródło
informuje to skrypt, gdzie jest katalog python!
źródło