# Koymalı mıyım? (shebang) Python betiklerinde ve ne biçim almalı?


829

Mesele Python scriptlerime koymalı mıyım? Hangi biçimde?

#!/usr/bin/env python 

veya

#!/usr/local/bin/python

Bunlar eşit derecede taşınabilir mi? En çok hangi form kullanılır?

Not: kasırga projesi shebang kullanır. Öte yandan Django projesi bunu yapmıyor.


70
İkincisi ise taşınabilir değildir ve olacak , birçok bilgisayarlarda değilse en başarısız.
Dietrich Epp

4
#!/usr/bin/pythonİlk seçenekle nasıl karşılaştırılır? Bunu bir çok örnek kodda görüyorum. Edit: Belki de cevap budur .. stackoverflow.com/a/2429517/1156245
geotheory


1
Her zaman kullan diyorum, Neden? "Zen Of Python" - Satır 2 - "Açık, örtük olmaktan iyidir." python.org/dev/peps/pep-0020
JayRizzo

2
Açıkçası, ikisi de "doğru" değildir, çünkü yazar olarak komut dosyası çalıştırıldığında Python'un doğru sürümünün nerede olacağını bilmiyorsunuzdur. Doğru dişi eklemek montajcının işi olmalıdır .
chepner

Yanıtlar:


1117

Herhangi bir komut dosyasındaki shebang satırı, komut dosyasının pythonterminalde önceden yazmadan veya bir dosya yöneticisinde çift tıklatıldığında (düzgün yapılandırıldığında) bağımsız bir yürütülebilir dosya gibi yürütülme yeteneğini belirler . Gerekli değildir, ancak genellikle oraya koyulur, böylece birisi bir düzenleyicide açılmış dosyayı gördüğünde, neye baktıklarını hemen bilirler. Ancak, kullandığınız shebang hat IS önemli.

Python 3 komut dosyalarının doğru kullanımı:

#!/usr/bin/env python3

Bu varsayılan olarak sürüm 3.latest olur. Python 2.7 için en uygun kullanım python2yerine python3.

Aşağıdakiler KULLANILMAMALIDIR (hem Python 2.x, hem de 3.x ile uyumlu kod yazdığınız nadir durumlar hariç):

#!/usr/bin/env python

Verilen bu önerilere nedeni, PEP 394 , yani pythonya başvurabilir python2veya python3farklı sistemlerde. Şu anda python2çoğu dağıtımdan bahsediyor , ancak bu muhtemelen bir noktada değişecek.

Ayrıca, KULLANMAYIN:

#!/usr/local/bin/python

"python bu durumlarda / usr / bin / python veya / bin / python'a kurulabilir, yukarıdaki #! başarısız olur."

- "#! / usr / bin / env python" vs "#! / usr / local / bin / python"


4
@EliasVanOotegem Eğer piton bulunabilir kesindir olamıyorsan /usr/bino belli nasıl olabilir o zaman envbulunacaktır /usr/bin. Python standart olmayan bir yere kurulursa, python'un standart olmayan bir şekilde kurulduğu ve komut dosyasının sonuç olarak hızlı bir şekilde başarısız olması gerektiği anlamına gelir. Python yorumlayıcının özellikleri hakkında varsayımlarda bulunmak ve en iyisini ummak gibi.
Dunes

65
@Dunes: envher zaman içinde bulunur /usr/bin/ve görevi kullanarak kutuları (python gibi) bulmaktır PATH. Python nasıl kurulursa kurulsun, yolu bu değişkene eklenecek ve envbulacaktır (eğer değilse, python kurulu değildir). Bu iş, var olmasınınenv tüm nedeni bu. Ortamı uyaran şeydir (yükleme yolları dahil env değişkenlerini ayarlayın ve yolları ekleyin). İnsanlar her zaman bu komutun ancak her zaman aynı yerde bulunursa çalışabileceğini anlamışlardır. Bu sadece verilen
Elias Van Ootegem

3
@JFSebastian: Haklısın, POSIX standardı tarafından garanti edilmiyor veya uygulanmıyor. Daha sonraki IEEE sürümlerinden birinin bazı çevre öğeleri içerdiğini varsaydım. Her iki şekilde: hayır, /usr/bin/env(evrensel?) Yaygın haricinde herhangi bir standart garanti edilmemektedir benimsenen kural ...
Elias Van Ootegem

6
Virtualenv kullanıyorsanız #! / Usr / local / bin / python olsa bile, yanlış olur.
nullas

6
Bu Tek sorun: göre PEP394 sadece kullanmalıdır bir pythonkomut Python 2 ile Aksi takdirde Python 3. uyumlu olduğunda yürütülebilir, uygun gelen seçenek işaret etmelidir python2ve python3.
1917

67

Gerçekten sadece bir tat meselesi. Mesele eklemek, insanların istedikleri takdirde komut dosyasını doğrudan çağırabileceği anlamına gelir (yürütülebilir olarak işaretlendiğini varsayarak); sadece atlamak pythonmanüel olarak çağrılmalıdır.

Programı çalıştırmanın sonucu her iki şekilde de etkilenmez; sadece araçların seçenekleri.


3
Sadece bu - hangi tarafı aldığınız önemli değil çünkü "doğru" taraf yok. Tamamen öznel bir karardır.
Amber

5
Diğer önemsiz kararlardan daha fazlası değil. en.wikipedia.org/wiki/Parkinson'ın_Law_of_Triviality
Amber

2
'Python' komutu olmadan doğrudan bir python dosyasını yürütebilir miyim?
Zen

5
@Zen Senaryonuza (#! / Usr / bin / env python) eklediğinizi varsayarsak, sadece betiğinizi çalıştırılabilir hale getirmeniz gerekir. Gibi bir şey chmod a+x [your-script].pyyürütülebilir yapmak gerekir ve daha sonra sadece ./[your-script.py]kabuk içinde arayabilirsiniz .
skålfyfan

9
GlassGhost tarafından cevap belirttiği gibi, orada olan tat yanında onu da dahil etmeleri için somut avantaj: bunların yerine ithal üzere pinti bir dosyadan daha, yürütülebilir bir senaryoyu okuyorsanız bu dosyanın bir gelecek okuyucular için açık hale getirir. Onlara sahip dillerdeki kamusal / özel erişim kontrol değiştiricilerine benzer şekilde, shebang'lar da belgelerin yanı sıra gerçek etkileri için de yararlıdır ve bazı durumlarda belge yönü aslında en önemlisidir.
Mark Amery

32

Mesele Python scriptlerime koymalı mıyım?

Aşağıdakileri belirtmek için bir Python betiğine bir shebang koyun:

  • bu modül komut dosyası olarak çalıştırılabilir
  • sadece python2, python3 üzerinde mi çalışabiliyor yoksa Python 2/3 uyumlu mu
  • POSIX'te, çalıştırılabilir pythondosyayı açıkça çağırmadan doğrudan komut dosyasını çalıştırmak istiyorsanız gereklidir

Bunlar eşit derecede taşınabilir mi? En çok hangi form kullanılır?

Elle bir shebang #!/usr/bin/env pythonyazarsanız, kullanmak için belirli bir nedeniniz yoksa her zaman kullanın . Bu form Windows'ta bile (Python başlatıcısı) anlaşılmıştır.

Not: kurulu komut dosyaları belirli bir python yürütülebilir dosyası kullanmalıdır, örn., /usr/bin/pythonVeya /home/me/.virtualenvs/project/bin/python. Kabuğunuzda bir sanal reklamı etkinleştirirseniz bazı araçların kırılması kötüdür. Neyse ki, doğru shebang çoğu durumda setuptoolsveya dağıtım paketi araçlarınız tarafından otomatik olarak oluşturulur (Windows'ta otomatik olarak setuptoolssarmalayıcı .exekomut dosyaları oluşturabilir ).

Başka bir deyişle, komut dosyası bir kaynak kasasındaysa, muhtemelen göreceksiniz #!/usr/bin/env python. Yüklü ise, shebang gibi belirli bir python çalıştırılabilirine giden bir yoldur #!/usr/local/bin/python (NOT: ikinci kategorideki yolları manuel olarak yazmamalısınız).

Kullanmak gerekip gerekmediğini seçmek için python, python2veya python3shebang içinde, bkz PEP 394 - Unix gibi Sistemleri "piton" Command :

  • ... pythonshebang satırında sadece Python 2 ve 3 ile uyumlu kaynak kodları için kullanılmalıdır.

  • Python'un varsayılan sürümünde nihai bir değişikliğe hazırlanırken, yalnızca Python 2 komut dosyalarının Python 3 ile kaynak uyumlu olacak şekilde güncellenmesi veya python2shebang satırında kullanılması gerekir.


3
Bir PEP'e bile atıfta bulunmanın ilk cevabının yeterli oyu yoktur. Ha? #!/usr/bin/env pythonKendisi için bir PEP var mı ?
binki

Lütfen kullanma #!/usr/bin/env python. Lütfen "her zaman kullan" seçeneğini önermeyin #!/usr/bin/env python. Bu, vakaların% 99'unda yapılacak yanlış bir şeydir (cevabınıza dahil etme nedeniniz).
Jay Sullivan

1
@JaySullivan Kaynak kasası ile kurulu komut dosyaları arasındaki farkı anlıyor musunuz? Önerinin arkasında duruyorum. İyi çalışıyor.
jfs

1
@jfs: Yorumumu tekrar okuduktan sonra ne demek istediğimi anlayamadım. Demek istediğim, çoğu insanın 'python' değil, 'python2' veya 'python3' kullanmak isteyeceği idi. Teknik olarak OP sorusu olan tam yol veya env yoluyla çözülüp çözülmeyeceği, cevapladınız ve ben bu konuda katılmıyorum.
Jay Sullivan

@JaySullivan katılıyorum. Cevabın içindeki alıntıyı okudun mu? Aynı şeyi söylüyor.
jfs

15

Birden fazla Python sürümünüz varsa ve komut dosyasının belirli bir sürüm altında çalışması gerekiyorsa, komut dosyası doğrudan yürütüldüğünde doğru olanın kullanıldığından emin olabilirsiniz, örneğin:

#!/usr/bin/python2.7

Komut dosyasının tam bir Python komut satırı üzerinden veya içe aktarma yoluyla çalıştırılabileceğini unutmayın; bu durumda she-bang yok sayılır. Ancak komut dosyaları doğrudan çalıştırılırsa, bu she-bang'ı kullanmak için iyi bir nedendir.

#!/usr/bin/env python genellikle daha iyi bir yaklaşımdır, ancak bu özel durumlara yardımcı olur.

Genellikle bir Python sanal ortamı oluşturmak daha iyi olur, bu durumda jenerik #!/usr/bin/env pythonsanalenv için doğru Python örneğini tanımlar.


Alan başarısız olmasına neden olmaz mı?
RandomInsano

1
@RandomInsano, sanmıyorum. Alanlar oldukça yaygın görünmektedir ve bunun net bir şekilde kabul edilen bir kullanım olarak çok fazla kanıt vardır. Ancak boş alanın muhtemelen daha kanonik kullanım olduğunu düşünüyorum.
Chris Johnson

1
Kesinlikle bu konuda haklısın. Sadece bash ve tcsh üzerinde test edildi.
RandomInsano

Sonuçları whichsize çalışacak bir dize verecektir, nokta. Kullanmak için bağırsakların hiçbiri için endişelenmenize gerek yok.
SDsolar

10

Senaryo çalıştırılabilir olması gerekiyorsa bir shebang eklemeniz gerekir. Ayrıca betiği, hedef platformda çalışacak şekilde, gövdeyi doğru bir şeye değiştiren bir yükleme yazılımı ile yüklemelisiniz. Bunun örnekleri distutils ve Distribute'dur.


1
#! sonra. / Usr / bin / env bunun içindir. Belirli bir Python yorumlayıcısına kodlama yapmak yarardan çok zarar verebilir. Başka bir Python sürümü kurmak veya dağıtımımızın Python'u ile özel bir Python kurulumu arasında geçiş yapmak çok kırılgandır.
vog

Ubuntu'da, sonuçlarını kullanmak whichotomatik olarak sistem komutları tarafından kullanılan varsayılanı seçecektir. Geneldir ve sistem onu ​​doğru kuruluma yönlendirir.
SDsolar

9

Mesele amacı, komut dosyasını kabuktan yürütmek istediğinizde komut dosyasının yorumlayıcı türünü tanımasıdır. Çoğunlukla ve her zaman değil, yorumlayıcıyı harici olarak sağlayarak komut dosyaları yürütürsünüz. Örnek kullanım:python-x.x script.py

Bu, bir shebang bildiriciniz olmasa bile işe yarayacaktır.

Birincisinin neden daha "taşınabilir" olduğu, sistem çalıştırılabilir dosyalarının bulunduğu tüm hedefleri açıklayan beyanınızı /usr/bin/enviçerir PATH.

NOT: Tornado kesinlikle shebangs kullanmaz ve Django kesinlikle kullanmaz. Uygulamanızın ana işlevini nasıl yürüttüğünüze göre değişir.

AYRICA: Python ile değişmez.


8

Cevap çok açık değilse Bazen (hayır evet ya olmadığına karar anlamına), o zaman çok fazla önemli değil, cevap gelene kadar sorunu göz ardı edebilirsiniz olduğu açıktır.

#!Tek amacı senaryoyu başlatılması içindir. Django kaynakları kendi başına yükler ve kullanır. Hangi tercümanın kullanılması gerektiğine asla karar vermek gerekmez. Bu şekilde, #!aslında burada bir anlam ifade etmiyor.

Genellikle, bir modülse ve komut dosyası olarak kullanılamıyorsa #!,. Öte yandan, bir modül kaynağı genellikle if __name__ == '__main__': ...işlevselliğin en azından bazı önemsiz testlerini içerir. Sonra #!yine mantıklı.

Kullanmanın iyi bir nedeni, #!hem Python 2 hem de Python 3 komut dosyalarını kullandığınızda - bunların Python'un farklı sürümleri tarafından yorumlanması gerektiğidir. Bu şekilde, pythonkomut dosyasını manuel olarak başlatırken neyin kullanılması gerekmediğini hatırlamanız gerekir #!. Bu tür komut dosyalarının bir karışımına sahipseniz, #!iç kısmı kullanmak, yürütülebilir hale getirmek ve yürütülebilir olarak (chmod ...) başlatmak iyi bir fikirdir .

MS-Windows kullanırken, bir #!anlamı yoktu - yakın zamana kadar. Python 3.3, #!satırı okuyan, Python'un yüklü sürümlerini algılayan ve Python'un doğru veya açıkça istenen sürümünü kullanan bir Windows Python Başlatıcısı (py.exe ve pyw.exe) sunar . Uzantı bir programla ilişkilendirilebileceğinden, Windows'ta Unix tabanlı sistemlerde yürütme bayrağıyla benzer davranışa sahip olabilirsiniz.


3

Python 3.6.1'i son zamanlarda Windows 7'ye kurduğumda, aynı zamanda shebang hattını işlemesi gereken Windows için Python Launcher'ı da yükledi. Ancak, Python Launcher'ın bunu yapmadığını buldum: shebang hattı göz ardı edildi ve Python 2.7.13 her zaman kullanıldı (ben py -3 kullanarak komut dosyası yürütmedim sürece).

Bunu düzeltmek için Windows kayıt defteri anahtarını düzenlemek zorunda kaldım HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Bu hala değere sahipti

"C:\Python27\python.exe" "%1" %*

önceki Python 2.7 kurulumumdan. Bu kayıt defteri anahtarı değerini olarak değiştirdim

"C:\Windows\py.exe" "%1" %*

ve Python Launcher dişi hat işlemesi yukarıda açıklandığı gibi çalıştı.


2

Takılı farklı modülleriniz varsa ve belirli bir python yüklemesi kullanmanız gerekiyorsa, ilk önce shebang sınırlı görünmektedir. Bununla birlikte, shebang'ın önce bir kabuk betiği olarak çağrılmasını ve ardından python'u seçmesini sağlamak için aşağıdaki gibi numaralar yapabilirsiniz. Bu çok esnek imo:

#!/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 $PREFERRED_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())

Ya da daha iyisi, belki de, birden fazla python betiğinde kodun yeniden kullanımını kolaylaştırmak için:

#!/bin/bash
"true" '''\'; source $(cd $(dirname ${BASH_SOURCE[@]}) &>/dev/null && pwd)/select.sh; exec $CHOSEN_PYTHON "$0" "$@"; exit 127; '''

ve select.sh öğesinde:

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
    CHOSEN_PYTHON=$PREFERRED_PYTHON
elif [ -x $ALTERNATIVE_PYTHON ]; then
    CHOSEN_PYTHON=$ALTERNATIVE_PYTHON
else
    CHOSEN_PYTHON=$FALLBACK_PYTHON
fi

1
Böyle bir poliglotun genel olarak iyi bir uygulama olduğundan emin olmasam da, kesinlikle çok ilginç bir yaklaşım ve muhtemelen burada en esnek cevap.
Ryan Amos

1
Çok havalı. Bunu yapabileceğini fark etmedim
user2233949

1

Yanıt: Yalnızca bunu komut satırı yürütülebilir komut dosyası yapmayı planlıyorsanız.

İşte prosedür:

Kullanmak için uygun shebang dizesini doğrulayarak başlayın:

which python

Bundan çıktı alın ve ilk satıra (shebang #! İle) ekleyin.

Sistemimde şöyle cevap veriyor:

$which python
/usr/bin/python

Yani senin shebang şöyle görünecek:

#!/usr/bin/python

Kaydettikten sonra, python bu ilk satırı bir yorum olarak göreceğinden, daha önce olduğu gibi çalışacaktır.

python filename.py

Bir komut yapmak için, .py uzantısını bırakmak üzere kopyalayın.

cp filename.py filename

Dosya sistemine bunun yürütülebilir olacağını söyleyin:

chmod +x filename

Test etmek için şunu kullanın:

./filename

En iyi uygulama, $ PATH'nızda bir yere taşımaktır, böylece yazmanız gereken tek şey dosya adının kendisidir.

sudo cp filename /usr/sbin

Bu şekilde her yerde çalışır (dosya adından önce ./ olmadan)


Bunun en iyi uygulama olduğundan şüpheliyim ve GlassGhost'un çözümünü kullanmanızı şiddetle tavsiye ederim .
colidyre

Bu yararlı buldum ve benim için güzel çalıştı. bu iyi açıklandı. Ancak bunun neden en iyi uygulama olmadığını belirten yorumları takdir ediyorum. Öğrenmeye hevesliyim.
Charles Carriere

0

Mutlak ve Mantıksal Yol:

Bu gerçekten Python yorumlayıcısına giden yolun taşınabilirlik açısından mutlak mı yoksa Mantıksal mı ( /usr/bin/env) olması gerektiği sorusudur .

Bu konuda ve kanıtları desteklemeden genel bir şekilde bahseden diğer Stack sitelerinde diğer cevaplarla karşılaştığımda , unix.stackexchange.com'daki bu soru üzerine gerçekten GERÇEKTEN , ayrıntılı testler ve analizler yaptım . Bu cevabı buraya yapıştırmak yerine, karşılaştırmalı analizle ilgilenenleri bu cevaba yönlendireceğim:

https://unix.stackexchange.com/a/566019/334294

Linux Mühendisi olarak amacım, geliştirici müşterilerim için her zaman en uygun ve optimize edilmiş ana bilgisayarları sağlamaktır, bu nedenle Python ortamları sorunu gerçekten sağlam bir cevaba ihtiyacım olan bir şeydi. Testten sonraki görüşüm , she-bang'daki mantıksal yolun (2) seçeneklerinden daha iyi olduğuydu.


-3

Önce kullan

which python

Bu, çıktıyı python yorumlayıcımın (ikili) bulunduğu konum olarak verecektir.

Bu çıktı aşağıdaki gibi olabilir

/usr/bin/python

veya

/bin/python

Şimdi uygun bir şekilde shebang hattını seçin ve kullanın.

Genelleştirmek için şunları kullanabiliriz:

#!/usr/bin/env

veya

#!/bin/env

3
Bu büyük olasılıkla diğer sistemlere taşınabilir olmayacaktır. #!/usr/bin/envsizin için doğru seçimi yapar.
fragmentedreality

Bu yüzden whichkomutu kullanıyorsunuz - sisteminiz için doğru dizeyi döndürecektir.
SDsolar

1
... ve daha sonra komut dosyası başka bir makinede her yürütüldüğünde which python, çıktı mevcut işten farklıysa tekrar çalıştırır ve komut dosyasını değiştirirsiniz
fragmentedreality

2
-1 Bu mümkün olan en kırılgan çözümdür. Yalnızca python betiğinizin yazıldığı sistem için doğru olması garanti edilir. Taşınabilirlik için #! / Usr / bin / env python3 kullanın
Myles Hollow
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.