Jawaban di bawah ini menyatakan bahwa itu hanyalah sebuah baris komentar. Itu tidak selalu terjadi. Saya memiliki "Halo, Dunia!" Skrip CGI (.py) yang hanya akan berjalan dan menampilkan halaman web dengan #!/usr/bin/env pythondi bagian atas.
Mereka mungkin berlari, tetapi tidak di lingkungan yang dimaksud
Nicholas Hamilton
18
Saya telah mengunjungi posting ini berkali-kali dalam 7 tahun karena saya kadang-kadang lupa dengan hashbang env. Salin pasta :)
BugHunterUK
Jawaban:
1083
Jika Anda memiliki beberapa versi Python yang diinstal, /usr/bin/envakan memastikan penerjemah yang digunakan adalah yang pertama di lingkungan Anda $PATH. Alternatifnya adalah dengan hardcode sesuatu seperti #!/usr/bin/python; tidak apa-apa, tapi kurang fleksibel.
Di Unix, file yang dapat dieksekusi yang dimaksudkan untuk ditafsirkan dapat menunjukkan penerjemah apa yang harus digunakan dengan memiliki #!di awal baris pertama, diikuti oleh penerjemah (dan bendera apa pun yang mungkin diperlukan).
Jika Anda berbicara tentang platform lain, tentu saja, aturan ini tidak berlaku (tetapi "garis shebang" tidak ada salahnya, dan akan membantu jika Anda pernah menyalin skrip itu ke platform dengan basis Unix, seperti Linux, Mac , dll).
Hanya untuk menambahkan: ini berlaku ketika Anda menjalankannya di Unix dengan menjadikannya executable ( chmod +x myscript.py) dan kemudian menjalankannya secara langsung ./myscript.py:, bukan hanya python myscript.py.
Craig McQueen
28
menggunakan envmemberikan fleksibilitas maksimum dalam hal pengguna dapat memilih juru bahasa untuk digunakan dengan mengubah PATH. Seringkali fleksibilitas ini tidak diperlukan meskipun dan downside adalah bahwa linux misalnya tidak dapat menggunakan nama skrip untuk nama proses psdan kembali ke "python". Ketika mengemas aplikasi python untuk distro misalnya saya akan menyarankan untuk tidak menggunakan env.
Sebuah kata peringatan penting, nilai pengembalian env pada akhirnya berakhir. Yang tidak mungkin mempengaruhi Anda jika Anda menjalankan proses berumur pendek. Namun, saya mengalami proses sekarat dengan pesan /usr/bin/env: Key has expiredsetelah berjam-jam.
malaverdiere
4
@malaverdiere dapatkah Anda menautkan ke sumber daya apa pun yang menjelaskan perilaku kedaluwarsa ini? Saya tidak dapat menemukan mereka.
Dalam komputasi, shebang (juga disebut hashbang, hashpling, pound bang, atau crunchbang) mengacu pada karakter "#!" ketika mereka adalah dua karakter pertama dalam arahan juru bahasa sebagai baris pertama dari file teks. Dalam sistem operasi mirip Unix, program loader mengambil keberadaan dua karakter ini sebagai indikasi bahwa file tersebut adalah skrip, dan mencoba untuk mengeksekusi skrip itu menggunakan interpreter yang ditentukan oleh sisa baris pertama dalam file.
Bahkan pada Windows, di mana garis shebang tidak menentukan penerjemah yang akan dijalankan, Anda dapat meneruskan opsi ke juru bahasa dengan menentukannya pada garis shebang. Saya merasa berguna untuk menjaga garis shebang generik dalam skrip satu kali (seperti yang saya tulis saat menjawab pertanyaan pada SO), jadi saya dapat dengan cepat mengujinya pada Windows dan ArchLinux .
The utilitas env memungkinkan Anda untuk memanggil perintah pada jalan:
Argumen yang tersisa pertama menentukan nama program yang akan dipanggil; itu dicari sesuai dengan PATHvariabel lingkungan. Argumen yang tersisa dilewatkan sebagai argumen untuk program itu.
Mudah ditemukan dengan Google - jika ada yang tahu kata kunci ("garis shebang" sangat penting).
Arafangion
14
Sebenarnya, penjelasan ini lebih jelas daripada referensi lain yang saya periksa di Google. Itu selalu lebih baik untuk mendapatkan 1 paragraf penjelasan yang menargetkan pertanyaan, daripada membaca seluruh manual yang membahas setiap potensi penggunaan.
@ulidtko: Mesin pencari yang menarik, pertimbangkan untuk menulis jawaban agar pertanyaan john garcias memiliki jawaban yang lebih baik.
Arafangion
1
"Bahkan di Windows, di mana garis shebang tidak menentukan penerjemah yang akan dijalankan, Anda dapat meneruskan opsi ke penerjemah dengan menentukannya di garis shebang." Itu hanya salah; jika hal seperti itu terjadi, itu karena penerjemah itu sendiri sedang memproses garis shebang. Jika penerjemah tidak memiliki pengakuan khusus untuk garis shebang, maka tidak ada yang terjadi. Windows tidak melakukan apa pun dengan garis shebang. "Yang mungkin Anda uraikan dalam kasus ini adalah peluncur python: python.org/dev/peps/pep-0397 .
Kaz
154
Memperluas sedikit jawaban yang lain, inilah sedikit contoh bagaimana skrip baris perintah Anda bisa mendapat masalah dengan penggunaan /usr/bin/envgaris shebang yang tidak hati-hati :
Salah satu cara untuk mencegah masalah semacam itu adalah dengan menggunakan nama perintah python berversi yang biasanya diinstal dengan sebagian besar Python:
Perbedaan antara lokal dan global. Jika which pythonkembali /usr/bin/python, jalur direktori lokal bisa sulit kode: #!/usr/bin/python. Tapi itu kurang fleksibel daripada #!/usr/bin/env pythonyang memiliki aplikasi global.
noobninja
85
Untuk menjalankan skrip python, kita perlu memberi tahu shell tiga hal:
Bahwa file tersebut adalah skrip
Penerjemah mana yang ingin kita jalankan skripnya
Jalan penerjemah tersebut
Shebang #!mencapai (1.). Shebang dimulai dengan a #karena #karakter adalah penanda komentar dalam banyak bahasa scripting. Oleh karena itu, isi garis shebang secara otomatis diabaikan oleh penerjemah.
The envperintah menyelesaikan (2.) dan (3). Mengutip "grawity,"
Penggunaan umum dari envperintah ini adalah untuk meluncurkan penerjemah, dengan memanfaatkan fakta bahwa env akan mencari $ PATH untuk perintah yang diperintahkan untuk diluncurkan. Karena garis shebang membutuhkan jalur absolut yang harus ditentukan, dan karena lokasi berbagai penafsir (perl, bash, python) dapat sangat bervariasi, itu biasa digunakan:
#!/usr/bin/env perl alih-alih mencoba menebak apakah itu adalah / bin / perl, / usr / bin / perl, / usr / local / bin / perl, / usr / local / pkg / perl, / fileserver / usr / bin / perl, atau / home / MrDaniel / usr / bin / perl pada sistem pengguna ...
Di sisi lain, env hampir selalu di / usr / bin / env. (Kecuali dalam kasus-kasus ketika tidak; beberapa sistem mungkin menggunakan / bin / env, tetapi itu adalah kesempatan yang cukup langka dan hanya terjadi pada sistem non-Linux.)
Anda tidak perlu saluran itu sama sekali. Sistem akan memanggil python dan kemudian python interpreter akan menjalankan skrip Anda.
Tetapi jika Anda berniat untuk menggunakan: $./myscript.py
Memanggilnya langsung seperti program normal atau skrip bash, Anda perlu menulis baris itu untuk menentukan sistem yang digunakan program untuk menjalankannya, (dan juga membuatnya dapat dieksekusi dengan chmod 755)
Itu membaca byte pertama file, dan membandingkannya #!.
Jika perbandingannya benar, maka seluruh baris diuraikan oleh kernel Linux, yang membuat execpanggilan lain dengan path /usr/bin/env pythondan file saat ini sebagai argumen pertama:
/usr/bin/env python /path/to/script.py
dan ini berfungsi untuk bahasa skrip apa pun yang digunakan #sebagai karakter komentar.
Dan ya, Anda dapat membuat loop tanpa batas dengan:
printf '#!/a\n'| sudo tee /a
sudo chmod +x /a
/a
Bash mengenali kesalahan:
-bash:/a: /a: bad interpreter:Too many levels of symbolic links
#! Kebetulan bisa dibaca manusia, tapi itu tidak wajib.
Jika file dimulai dengan byte yang berbeda, maka execpanggilan sistem akan menggunakan penangan yang berbeda. Handler bawaan yang paling penting adalah untuk file yang dapat dieksekusi ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 yang memeriksa byte 7f 45 4c 46(yang juga merupakan manusia dapat dibaca untuk .ELF). Mari kita konfirmasi dengan membaca 4 byte pertama /bin/ls, yang merupakan executable ELF:
Saya tidak berpikir POSIX menentukan shebangs: https://unix.stackexchange.com/a/346214/32558 , meskipun ia menyebutkan bagian rasional, dan dalam bentuk "jika skrip yang dapat dieksekusi didukung oleh sistem, sesuatu mungkin terjadi". macOS dan FreeBSD juga tampaknya mengimplementasikannya.
PATH motivasi pencarian
Kemungkinan, satu motivasi besar untuk keberadaan shebang adalah kenyataan bahwa di Linux, kita sering ingin menjalankan perintah PATHhanya dari :
basename-of-command
dari pada:
/full/path/to/basename-of-command
Tapi kemudian, tanpa mekanisme shebang, bagaimana Linux tahu cara meluncurkan setiap jenis file?
Hardcoding ekstensi dalam perintah:
basename-of-command.py
atau menerapkan pencarian PATH pada setiap penerjemah:
python basename-of-command
akan menjadi suatu kemungkinan, tetapi ini memiliki masalah besar bahwa semuanya rusak jika kita pernah memutuskan untuk mengubah perintah ke bahasa lain.
Secara teknis, dalam Python, ini hanya sebuah baris komentar.
Baris ini hanya digunakan jika Anda menjalankan skrip py dari shell (dari baris perintah). Ini dikenal sebagai " Shebang !" , dan digunakan dalam berbagai situasi, tidak hanya dengan skrip Python.
Di sini, ia memerintahkan shell untuk memulai versi Python tertentu (untuk menjaga sisa file.
Shebang adalah konsep Unix. Mungkin perlu disebutkan bahwa ini juga berfungsi pada Windows jika Anda telah menginstal peluncur Pythonpy.exe . Ini adalah bagian dari instalasi Python standar.
florisla
38
Alasan utama untuk melakukan ini adalah untuk membuat skrip portable di seluruh lingkungan sistem operasi.
Misalnya di bawah mingw, skrip python gunakan:
#!/c/python3k/python
dan di bawah distribusi GNU / Linux itu adalah:
#!/usr/local/bin/python
atau
#!/usr/bin/python
dan di bawah sistem Unix sw / hw komersial terbaik semua (OS / X), itu adalah:
#!/Applications/MacPython 2.5/python
atau di FreeBSD:
#!/usr/local/bin/python
Namun semua perbedaan ini dapat membuat skrip portable di semua dengan menggunakan:
Di bawah MacOSX, itu juga /usr/bin/python. Di Linux, Python yang diinstal oleh sistem juga hampir pasti /usr/bin/python(saya belum pernah melihat yang lain dan itu tidak masuk akal). Perhatikan bahwa mungkin ada sistem yang tidak memiliki /usr/bin/env.
Albert
1
Jika Anda menggunakan OSX dan menggunakan Homebrew dan mengikuti petunjuk instalasi default mereka, itu akan berada di bawah #! / Usr / local / bin / python
Will
@ Jean-PaulCalderone: Lihat jawaban saaj di bawah ini.
pydsigner
Pembaruan untuk tahun 2018: Bare pythontidak terlalu portabel, itu adalah penerjemah default Python. Arch Linux default ke Python 3 untuk waktu yang lama dan mungkin distribusi memikirkannya juga karena Python 2 hanya didukung hingga 2020.
mati865
22
Mungkin masuk akal untuk menekankan satu hal yang paling banyak terlewatkan, yang dapat mencegah pemahaman langsung. Saat Anda mengetikkan pythonterminal, biasanya Anda tidak menyediakan jalur lengkap. Sebagai gantinya, executable terlihat dalam PATHvariabel lingkungan. Pada gilirannya, ketika Anda ingin menjalankan program Python secara langsung,, /path/to/app.pyseseorang harus memberi tahu shell apa yang harus digunakan juru bahasa (melalui hashbang , apa yang dijelaskan oleh kontributor lain di atas).
Hashbang mengharapkan jalan penuh ke penerjemah. Jadi untuk menjalankan program Python Anda secara langsung, Anda harus memberikan path lengkap ke Python binary yang sangat bervariasi, terutama mengingat penggunaan virtualenv . Untuk mengatasi portabilitas, trik /usr/bin/envyang digunakan. Yang terakhir ini awalnya dimaksudkan untuk mengubah lingkungan di tempat dan menjalankan perintah di dalamnya. Ketika tidak ada perubahan disediakan itu menjalankan perintah di lingkungan saat ini, yang secara efektif menghasilkan PATHpencarian yang sama yang melakukan trik.
Itu hanya menentukan penerjemah apa yang ingin Anda gunakan. Untuk memahami hal ini, buat file melalui terminal dengan melakukan touch test.py, lalu ketikkan ke file itu sebagai berikut:
#!/usr/bin/env python3print"test"
dan lakukan chmod +x test.pyuntuk membuat skrip Anda dapat dieksekusi. Setelah ini ketika Anda melakukannya, ./test.pyAnda akan mendapatkan pesan kesalahan:
File"./test.py", line 2print"test"^SyntaxError:Missing parentheses in call to 'print'
karena python3 tidak mendukung operator cetak.
Sekarang, lanjutkan dan ubah baris pertama kode Anda ke:
#!/usr/bin/env python2
dan itu akan berhasil, mencetak testke stdout, karena python2 mendukung operator cetak. Jadi, sekarang Anda telah belajar cara beralih antar penerjemah skrip.
Sepertinya saya suka menjalankan file yang sama tanpa garis itu.
Jika demikian, maka mungkin Anda menjalankan program Python di Windows? Windows tidak menggunakan baris itu — sebaliknya, ia menggunakan ekstensi nama file untuk menjalankan program yang terkait dengan ekstensi file.
Namun pada tahun 2011, "peluncur Python" dikembangkan yang (sampai taraf tertentu) meniru perilaku Linux ini untuk Windows. Ini terbatas hanya untuk memilih interpreter Python mana yang dijalankan - misalnya untuk memilih antara Python 2 dan Python 3 pada sistem di mana keduanya diinstal. Peluncur secara opsional diinstal sebagai py.exeoleh instalasi Python, dan dapat dikaitkan dengan .pyfile sehingga peluncur akan memeriksa baris itu dan pada gilirannya meluncurkan versi interpreter Python yang ditentukan.
Dia mungkin juga menggunakan $ python myscript.py.
Sinan Ünür
Saya membuat kesalahan dengan tidak memiliki baris dan menggunakan python script.py, dan suatu hari saya baru saja melakukannya.
Guagua
8
Ini dimaksudkan sebagai lebih banyak informasi historis daripada jawaban "nyata".
Ingatlah bahwa di masa lalu Anda memiliki BANYAK sistem operasi unix like yang perancangnya semua memiliki gagasan sendiri tentang di mana harus meletakkan barang, dan kadang-kadang tidak termasuk Python, Perl, Bash, atau banyak hal GNU / Open Source lainnya sama sekali .
Ini bahkan berlaku untuk distribusi Linux yang berbeda. Di Linux - pra-FHS [1] -Anda mungkin memiliki python di / usr / bin / atau / usr / local / bin /. Atau mungkin belum diinstal, jadi Anda membuat sendiri dan memasukkannya ke ~ / bin
Solaris adalah yang terburuk yang pernah saya kerjakan, sebagian sebagai transisi dari Berkeley Unix ke Sistem V. Anda bisa berakhir dengan hal-hal di / usr /, / usr / local /, / usr / ucb, / opt / dll. Ini bisa membuat untuk beberapa benar-benar jalur yang panjang. Saya memiliki kenangan tentang hal-hal dari Sunfreeware.com menginstal setiap paket di direktori itu sendiri, tetapi saya tidak dapat mengingat apakah itu menyinkronkan binari ke / usr / bin atau tidak.
Oh, dan terkadang / usr / bin berada di server NFS [2].
Jadi envutilitas dikembangkan untuk mengatasi ini.
Kemudian Anda bisa menulis #!/bin/env interpreterdan selama jalannya benar, hal-hal yang wajar memiliki peluang untuk berjalan. Tentu saja, masuk akal berarti (untuk Python dan Perl) bahwa Anda juga telah menetapkan variabel lingkungan yang sesuai. Untuk bash / ksh / zsh itu hanya berfungsi.
Ini penting karena orang-orang sedang membagikan skrip shell (seperti perl dan python) dan jika Anda ingin mengode / usr / bin / python di workstation Red Hat Linux Anda, itu akan sangat buruk pada SGI ... well, tidak , Saya pikir IRIX meletakkan python di tempat yang tepat. Tetapi pada stasiun Sparc mungkin tidak berjalan sama sekali.
Saya merindukan stasiun sparc saya. Tapi tidak banyak. Ok, sekarang Anda membuat saya berkeliling di E-Bay. Bajingan.
Jika Anda menjalankan skrip Anda di lingkungan virtual, katakanlah venv, mengeksekusi which pythonsambil bekerja venvakan menampilkan jalur ke juru bahasa Python:
~/Envs/venv/bin/python
Perhatikan bahwa nama lingkungan virtual tertanam di jalur ke penerjemah Python. Oleh karena itu, meng-hardcoding jalur ini dalam skrip Anda akan menyebabkan dua masalah:
Jika Anda mengunggah skrip ke repositori, Anda memaksa pengguna lain untuk memiliki nama lingkungan virtual yang sama . Ini jika mereka mengidentifikasi masalahnya terlebih dahulu.
Anda tidak akan dapat menjalankan skrip di beberapa lingkungan virtual bahkan jika Anda memiliki semua paket yang diperlukan di lingkungan virtual lainnya.
Oleh karena itu, untuk menambah jawaban Jonathan , shebang yang ideal adalah #!/usr/bin/env python, tidak hanya untuk portabilitas di seluruh OS tetapi untuk portabilitas di lingkungan virtual juga!
Mempertimbangkan masalah portabilitas di antara python2dan python3, Anda harus selalu menentukan versi mana pun kecuali jika program Anda kompatibel dengan keduanya.
Beberapa distribusi pengiriman pythonterhubung python3untuk sementara waktu sekarang - jangan bergantung pada pythonkeberadaan python2.
Untuk mentolerir perbedaan antar platform, semua kode baru yang perlu memanggil juru bahasa Python tidak boleh menentukan python, tetapi lebih baik menentukan python2 atau python3 (atau versi python2.x dan python3.x yang lebih spesifik; lihat Migration Notes ) . Perbedaan ini harus dibuat di shebangs, ketika memohon dari skrip shell, ketika memohon melalui system () panggilan, atau ketika memohon dalam konteks lain.
Ini memungkinkan Anda untuk memilih executable yang ingin Anda gunakan; yang sangat berguna jika mungkin Anda memiliki beberapa pemasangan python, dan modul yang berbeda di masing-masing dan ingin memilih. misalnya
#!/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
di bagian atas.Jawaban:
Jika Anda memiliki beberapa versi Python yang diinstal,
/usr/bin/env
akan memastikan penerjemah yang digunakan adalah yang pertama di lingkungan Anda$PATH
. Alternatifnya adalah dengan hardcode sesuatu seperti#!/usr/bin/python
; tidak apa-apa, tapi kurang fleksibel.Di Unix, file yang dapat dieksekusi yang dimaksudkan untuk ditafsirkan dapat menunjukkan penerjemah apa yang harus digunakan dengan memiliki
#!
di awal baris pertama, diikuti oleh penerjemah (dan bendera apa pun yang mungkin diperlukan).Jika Anda berbicara tentang platform lain, tentu saja, aturan ini tidak berlaku (tetapi "garis shebang" tidak ada salahnya, dan akan membantu jika Anda pernah menyalin skrip itu ke platform dengan basis Unix, seperti Linux, Mac , dll).
sumber
chmod +x myscript.py
) dan kemudian menjalankannya secara langsung./myscript.py
:, bukan hanyapython myscript.py
.env
memberikan fleksibilitas maksimum dalam hal pengguna dapat memilih juru bahasa untuk digunakan dengan mengubah PATH. Seringkali fleksibilitas ini tidak diperlukan meskipun dan downside adalah bahwa linux misalnya tidak dapat menggunakan nama skrip untuk nama prosesps
dan kembali ke "python". Ketika mengemas aplikasi python untuk distro misalnya saya akan menyarankan untuk tidak menggunakanenv
.py
peluncur dapat menggunakan garis shebang di Windows. Ini termasuk dalam Python 3.3 atau dapat diinstal secara independen ./usr/bin/env: Key has expired
setelah berjam-jam.Itu disebut garis shebang . Sebagaimana dijelaskan oleh entri Wikipedia :
Lihat juga entri FAQ Unix .
Bahkan pada Windows, di mana garis shebang tidak menentukan penerjemah yang akan dijalankan, Anda dapat meneruskan opsi ke juru bahasa dengan menentukannya pada garis shebang. Saya merasa berguna untuk menjaga garis shebang generik dalam skrip satu kali (seperti yang saya tulis saat menjawab pertanyaan pada SO), jadi saya dapat dengan cepat mengujinya pada Windows dan ArchLinux .
The utilitas env memungkinkan Anda untuk memanggil perintah pada jalan:
sumber
Memperluas sedikit jawaban yang lain, inilah sedikit contoh bagaimana skrip baris perintah Anda bisa mendapat masalah dengan penggunaan
/usr/bin/env
garis shebang yang tidak hati-hati :Modul json tidak ada di Python 2.5.
Salah satu cara untuk mencegah masalah semacam itu adalah dengan menggunakan nama perintah python berversi yang biasanya diinstal dengan sebagian besar Python:
Jika Anda hanya perlu membedakan antara Python 2.x dan Python 3.x, rilis terbaru Python 3 juga memberikan
python3
nama:sumber
which python
kembali/usr/bin/python
, jalur direktori lokal bisa sulit kode:#!/usr/bin/python
. Tapi itu kurang fleksibel daripada#!/usr/bin/env python
yang memiliki aplikasi global.Untuk menjalankan skrip python, kita perlu memberi tahu shell tiga hal:
Shebang
#!
mencapai (1.). Shebang dimulai dengan a#
karena#
karakter adalah penanda komentar dalam banyak bahasa scripting. Oleh karena itu, isi garis shebang secara otomatis diabaikan oleh penerjemah.The
env
perintah menyelesaikan (2.) dan (3). Mengutip "grawity,"sumber
Mungkin pertanyaan Anda dalam pengertian ini:
Jika Anda ingin menggunakan:
$python myscript.py
Anda tidak perlu saluran itu sama sekali. Sistem akan memanggil python dan kemudian python interpreter akan menjalankan skrip Anda.
Tetapi jika Anda berniat untuk menggunakan:
$./myscript.py
Memanggilnya langsung seperti program normal atau skrip bash, Anda perlu menulis baris itu untuk menentukan sistem yang digunakan program untuk menjalankannya, (dan juga membuatnya dapat dieksekusi dengan
chmod 755
)sumber
The
exec
system call dari kernel Linux mengerti shebangs (#!
) nativeKetika Anda melakukannya di bash:
di Linux, ini memanggil
exec
system call dengan path./something
.Baris kernel ini dipanggil pada file yang diteruskan ke
exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25Itu membaca byte pertama file, dan membandingkannya
#!
.Jika perbandingannya benar, maka seluruh baris diuraikan oleh kernel Linux, yang membuat
exec
panggilan lain dengan path/usr/bin/env python
dan file saat ini sebagai argumen pertama:dan ini berfungsi untuk bahasa skrip apa pun yang digunakan
#
sebagai karakter komentar.Dan ya, Anda dapat membuat loop tanpa batas dengan:
Bash mengenali kesalahan:
#!
Kebetulan bisa dibaca manusia, tapi itu tidak wajib.Jika file dimulai dengan byte yang berbeda, maka
exec
panggilan sistem akan menggunakan penangan yang berbeda. Handler bawaan yang paling penting adalah untuk file yang dapat dieksekusi ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305 yang memeriksa byte7f 45 4c 46
(yang juga merupakan manusia dapat dibaca untuk.ELF
). Mari kita konfirmasi dengan membaca 4 byte pertama/bin/ls
, yang merupakan executable ELF:keluaran:
Jadi ketika kernel melihat byte-byte itu, ia mengambil file ELF, memasukkannya ke dalam memori dengan benar, dan memulai proses baru dengannya. Lihat juga: Bagaimana kernel menjalankan file biner yang dapat dieksekusi berjalan di linux?
Akhirnya, Anda dapat menambahkan penangan shebang Anda sendiri dengan
binfmt_misc
mekanismenya. Misalnya, Anda dapat menambahkan penangan khusus untuk.jar
file . Mekanisme ini bahkan mendukung penangan melalui ekstensi file. Aplikasi lain adalah untuk menjalankan executable dari arsitektur yang berbeda dengan QEMU .Saya tidak berpikir POSIX menentukan shebangs: https://unix.stackexchange.com/a/346214/32558 , meskipun ia menyebutkan bagian rasional, dan dalam bentuk "jika skrip yang dapat dieksekusi didukung oleh sistem, sesuatu mungkin terjadi". macOS dan FreeBSD juga tampaknya mengimplementasikannya.
PATH
motivasi pencarianKemungkinan, satu motivasi besar untuk keberadaan shebang adalah kenyataan bahwa di Linux, kita sering ingin menjalankan perintah
PATH
hanya dari :dari pada:
Tapi kemudian, tanpa mekanisme shebang, bagaimana Linux tahu cara meluncurkan setiap jenis file?
Hardcoding ekstensi dalam perintah:
atau menerapkan pencarian PATH pada setiap penerjemah:
akan menjadi suatu kemungkinan, tetapi ini memiliki masalah besar bahwa semuanya rusak jika kita pernah memutuskan untuk mengubah perintah ke bahasa lain.
Shebangs memecahkan masalah ini dengan indah.
sumber
Secara teknis, dalam Python, ini hanya sebuah baris komentar.
Baris ini hanya digunakan jika Anda menjalankan skrip py dari shell (dari baris perintah). Ini dikenal sebagai " Shebang !" , dan digunakan dalam berbagai situasi, tidak hanya dengan skrip Python.
Di sini, ia memerintahkan shell untuk memulai versi Python tertentu (untuk menjaga sisa file.
sumber
py.exe
. Ini adalah bagian dari instalasi Python standar.Alasan utama untuk melakukan ini adalah untuk membuat skrip portable di seluruh lingkungan sistem operasi.
Misalnya di bawah mingw, skrip python gunakan:
dan di bawah distribusi GNU / Linux itu adalah:
atau
dan di bawah sistem Unix sw / hw komersial terbaik semua (OS / X), itu adalah:
atau di FreeBSD:
Namun semua perbedaan ini dapat membuat skrip portable di semua dengan menggunakan:
sumber
/usr/bin/python
. Di Linux, Python yang diinstal oleh sistem juga hampir pasti/usr/bin/python
(saya belum pernah melihat yang lain dan itu tidak masuk akal). Perhatikan bahwa mungkin ada sistem yang tidak memiliki/usr/bin/env
.python
tidak terlalu portabel, itu adalah penerjemah default Python. Arch Linux default ke Python 3 untuk waktu yang lama dan mungkin distribusi memikirkannya juga karena Python 2 hanya didukung hingga 2020.Mungkin masuk akal untuk menekankan satu hal yang paling banyak terlewatkan, yang dapat mencegah pemahaman langsung. Saat Anda mengetikkan
python
terminal, biasanya Anda tidak menyediakan jalur lengkap. Sebagai gantinya, executable terlihat dalamPATH
variabel lingkungan. Pada gilirannya, ketika Anda ingin menjalankan program Python secara langsung,,/path/to/app.py
seseorang harus memberi tahu shell apa yang harus digunakan juru bahasa (melalui hashbang , apa yang dijelaskan oleh kontributor lain di atas).Hashbang mengharapkan jalan penuh ke penerjemah. Jadi untuk menjalankan program Python Anda secara langsung, Anda harus memberikan path lengkap ke Python binary yang sangat bervariasi, terutama mengingat penggunaan virtualenv . Untuk mengatasi portabilitas, trik
/usr/bin/env
yang digunakan. Yang terakhir ini awalnya dimaksudkan untuk mengubah lingkungan di tempat dan menjalankan perintah di dalamnya. Ketika tidak ada perubahan disediakan itu menjalankan perintah di lingkungan saat ini, yang secara efektif menghasilkanPATH
pencarian yang sama yang melakukan trik.Sumber dari unix stackexchange
sumber
Ini adalah konvensi shell yang memberi tahu shell program mana yang dapat menjalankan skrip.
menyelesaikan ke jalur ke biner Python.
sumber
Ini direkomendasikan, diusulkan dalam dokumentasi:
dari http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
sumber
Anda dapat mencoba masalah ini menggunakan virtualenv
Inilah test.py
Buat lingkungan virtual
aktifkan masing-masing lingkungan lalu periksa perbedaannya
sumber
Itu hanya menentukan penerjemah apa yang ingin Anda gunakan. Untuk memahami hal ini, buat file melalui terminal dengan melakukan
touch test.py
, lalu ketikkan ke file itu sebagai berikut:dan lakukan
chmod +x test.py
untuk membuat skrip Anda dapat dieksekusi. Setelah ini ketika Anda melakukannya,./test.py
Anda akan mendapatkan pesan kesalahan:karena python3 tidak mendukung operator cetak.
Sekarang, lanjutkan dan ubah baris pertama kode Anda ke:
dan itu akan berhasil, mencetak
test
ke stdout, karena python2 mendukung operator cetak. Jadi, sekarang Anda telah belajar cara beralih antar penerjemah skrip.sumber
Jika demikian, maka mungkin Anda menjalankan program Python di Windows? Windows tidak menggunakan baris itu — sebaliknya, ia menggunakan ekstensi nama file untuk menjalankan program yang terkait dengan ekstensi file.
Namun pada tahun 2011, "peluncur Python" dikembangkan yang (sampai taraf tertentu) meniru perilaku Linux ini untuk Windows. Ini terbatas hanya untuk memilih interpreter Python mana yang dijalankan - misalnya untuk memilih antara Python 2 dan Python 3 pada sistem di mana keduanya diinstal. Peluncur secara opsional diinstal sebagai
py.exe
oleh instalasi Python, dan dapat dikaitkan dengan.py
file sehingga peluncur akan memeriksa baris itu dan pada gilirannya meluncurkan versi interpreter Python yang ditentukan.sumber
$ python myscript.py
.Ini dimaksudkan sebagai lebih banyak informasi historis daripada jawaban "nyata".
Ingatlah bahwa di masa lalu Anda memiliki BANYAK sistem operasi unix like yang perancangnya semua memiliki gagasan sendiri tentang di mana harus meletakkan barang, dan kadang-kadang tidak termasuk Python, Perl, Bash, atau banyak hal GNU / Open Source lainnya sama sekali .
Ini bahkan berlaku untuk distribusi Linux yang berbeda. Di Linux - pra-FHS [1] -Anda mungkin memiliki python di / usr / bin / atau / usr / local / bin /. Atau mungkin belum diinstal, jadi Anda membuat sendiri dan memasukkannya ke ~ / bin
Solaris adalah yang terburuk yang pernah saya kerjakan, sebagian sebagai transisi dari Berkeley Unix ke Sistem V. Anda bisa berakhir dengan hal-hal di / usr /, / usr / local /, / usr / ucb, / opt / dll. Ini bisa membuat untuk beberapa benar-benar jalur yang panjang. Saya memiliki kenangan tentang hal-hal dari Sunfreeware.com menginstal setiap paket di direktori itu sendiri, tetapi saya tidak dapat mengingat apakah itu menyinkronkan binari ke / usr / bin atau tidak.
Oh, dan terkadang / usr / bin berada di server NFS [2].
Jadi
env
utilitas dikembangkan untuk mengatasi ini.Kemudian Anda bisa menulis
#!/bin/env interpreter
dan selama jalannya benar, hal-hal yang wajar memiliki peluang untuk berjalan. Tentu saja, masuk akal berarti (untuk Python dan Perl) bahwa Anda juga telah menetapkan variabel lingkungan yang sesuai. Untuk bash / ksh / zsh itu hanya berfungsi.Ini penting karena orang-orang sedang membagikan skrip shell (seperti perl dan python) dan jika Anda ingin mengode / usr / bin / python di workstation Red Hat Linux Anda, itu akan sangat buruk pada SGI ... well, tidak , Saya pikir IRIX meletakkan python di tempat yang tepat. Tetapi pada stasiun Sparc mungkin tidak berjalan sama sekali.
Saya merindukan stasiun sparc saya. Tapi tidak banyak. Ok, sekarang Anda membuat saya berkeliling di E-Bay. Bajingan.
[1] Standar Hirarki sistem file. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] Ya, dan terkadang orang masih melakukan hal-hal seperti itu. Dan tidak, saya tidak memakai lobak ATAU bawang di ikat pinggang saya.
sumber
Jika Anda menjalankan skrip Anda di lingkungan virtual, katakanlah
venv
, mengeksekusiwhich python
sambil bekerjavenv
akan menampilkan jalur ke juru bahasa Python:~/Envs/venv/bin/python
Perhatikan bahwa nama lingkungan virtual tertanam di jalur ke penerjemah Python. Oleh karena itu, meng-hardcoding jalur ini dalam skrip Anda akan menyebabkan dua masalah:
Oleh karena itu, untuk menambah jawaban Jonathan , shebang yang ideal adalah
#!/usr/bin/env python
, tidak hanya untuk portabilitas di seluruh OS tetapi untuk portabilitas di lingkungan virtual juga!sumber
Mempertimbangkan masalah portabilitas di antara
python2
danpython3
, Anda harus selalu menentukan versi mana pun kecuali jika program Anda kompatibel dengan keduanya.Beberapa distribusi pengiriman
python
terhubungpython3
untuk sementara waktu sekarang - jangan bergantung padapython
keberadaanpython2
.Ini ditekankan oleh PEP 394 :
sumber
Ini memberi tahu penerjemah versi python mana untuk menjalankan program ketika Anda memiliki banyak versi python.
sumber
Ini memungkinkan Anda untuk memilih executable yang ingin Anda gunakan; yang sangat berguna jika mungkin Anda memiliki beberapa pemasangan python, dan modul yang berbeda di masing-masing dan ingin memilih. misalnya
sumber
ini memberitahu script di mana direktori python!
sumber