Shebang'ımda ortam değişkenlerini nasıl kullanabilirim?


34

Belirli bir python kurulumuyla çalıştırılması gereken bir Python betiğim var. Bir shebang yapmak için çalışacak bir yolu var mı $FOO/bar/MyCustomPython?

Yanıtlar:


29

Shebang hattı çok sınırlı. Birçok unix değişkeninde (Linux dahil) sadece iki kelimeniz olabilir: bir komut ve bir argüman. Genellikle bir uzunluk sınırlaması da vardır.

Genel çözüm küçük bir kabuk ambalajı yazmaktır. Python komut dosyasını adlandırın foo.pyve kabuk komut dosyasını yanına koyun foo.pyve çağırın foo. Bu yaklaşım Python betiğinde herhangi bir başlık gerektirmez.

#!/bin/sh
exec "$FOO/bar/MyCustomPython" "$0.py" "$@"

Bir başka cazip yaklaşım, yukarıdaki gibi bir sarmalayıcı komut dosyası yazmak #!/path/to/wrapper/scriptve Python komut dosyasına shebang satırı olarak koymaktır . Ancak, çoğu sendika shebang scriptlerinin zincirlenmesini desteklemiyor, bu yüzden bu işe yaramayacak.

Eğer MyCustomPythonidi $PATHşunu kullanabilirsiniz envbana arama:

#!/usr/bin/env MyCustomPython
import 

Yine bir başka yaklaşım, betiğin hem geçerli bir kabuk betiği (kendi başına doğru Python yorumlayıcısını yükleyen) hem de hedef dilde geçerli bir betiği (burada Python) ayarlamasıdır. Bu, hedef diliniz için böyle bir çift dilli komut dosyası yazmanın bir yolunu bulmanızı gerektirir. Perl'de buna bilinir if $running_under_some_shell.

#!/bin/sh
eval 'exec "$FOO/bar/MyCustomPerl" -wS $0 ${1+"$@"}'
    if $running_under_some_shell;
use 

Python'da da aynı etkiyi elde etmenin bir yolu. Kabuğunda, "true"bir trueargümanları (iki adet tek karakter dizileri göz ardı programı :ve ') ve gerçek değer geri gönderir. Python'da, "true"bir boolean olarak yorumlandığında doğru olan bir dizedir, bu yüzden bu ifher zaman doğru olan ve bir string değişmezini yürüten bir komuttur.

#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import 

Rosetta kodunda, başka dillerde de böyle çift dilli komut dosyaları bulunur.


1
@Chris: Her şey tek tırnak içinde. Lütfen açıklayın…
Stéphane Gimenez 17:11

1
Sen kanlı bir büyücüsün ... Bu harika. Bunu PYTHONPATH, kök erişimim olmayan bir sistemdeki CGI betiği için standart olmayan bir konumdan modülleri yüklemek üzere env değişkenini düzenlemek için kullandım. Hayat kurtarıcı. Tekrar teşekkürler.
wspurgin

12

Shebang satırları değişken genişlemeden geçmez, bu yüzden $FOO/MyCustomPythondollar-FOO -... adında bir yürütülebilir dosyayı arayacağı gibi kullanamazsınız .

Alternatif olarak, Shebang'ınızın tercüman olarak bir kabuk betiğine işaret etmesini sağlamaktır ve bu kabuk betiği daha sonra doğru besini bulmak ve yürütmek için ortam değişkenlerini kullanabilir.

Örnek: Aşağıdaki içeriğe sahip bir mypython.shkomut dosyası oluşturun /usr/local/bin(veya üzerinizdeki başka bir dizin $PATH):

#! /bin/sh
PYTHON="$FOO/bar/MyCustomPython"
exec "$PYTHON" "$@"

o zaman bir Python komut aracılığıyla yürütülecek olması bu mesele satırını kullanabilirsiniz MyCustomPythonyoluyla mypython.sh:

#!/usr/bin/env mypython.sh

6
Kullanmayın $python, $PYTHONkurallara göre, ortam değişkenlerini (PAGER, EDITOR, SHELL ... $PYTHONkomut dosyanızdaki bir ortam değişkeni değil) ve iç kabuk değişkenlerini (BASH_VERSION, RANDOM, ...) büyük harflerle yazıyoruz. Diğer tüm değişken isimleri en az bir küçük harf içermelidir. Bu sözleşme, çevresel ve dahili değişkenleri yanlışlıkla geçersiz kılmayı önler. Ayrıca, komut dosyalarınız için uzantıları kullanmayın. Komut dosyaları, çalıştırabileceğiniz yeni komutları tanımlar ve komutlara genellikle uzantı verilmez.
Chris Down

4

Özel python kurulumunun mutlak yolunu kullanabilir ya da içine koyabilir $PATHve kullanabilirsiniz #!/usr/bin/env [command]. Aksi takdirde, bunun için bir sarmalayıcı yazın ve execörnek olarak işlem görüntüsünü değiştirmek için kullanın :

#!/bin/bash
exec "$ENV/python" "$@"

3

Öncelikle, Python sürümünüzün halihazırda kurulu olan standart Python'dan (örneğin, ek bir modül) ne kadar farklı olduğunu ve ardından 'switch' programının başında Python'un nasıl adlandırıldığını belirleyin:

#!/usr/bin/python
import os
import sys
try:
    import MyCustomModule
except ImportError:
    # only need to use expandvar if you know the string below has an envvar
    custprog = os.path.expandvar("$FOO/bar/MyCustomPython")
    os.execv(custprog, sys.argv) # call alternate python with the same arguments
    raise SystemExit('could not call %s' % custprog)
# if we get here, then we have the correct python interpreter

Bu, programın başka herhangi bir Python örneği tarafından çağrılmasına izin vermelidir. Sistemin pythonunda modül olarak alınamayan yerleşik sql kütüphanesine sahip bir örnek için benzer bir şey yapıyorum.


0

Somut yol seçenekleriyle değiştirebiliyorsanız $FOO, doğrudan bir özel ayar $FOO/bar/MyCustomPythonyaparak envshebang hattına özel Python sürümünüzü nerede arayacağınızı PATHsöyleyebilirsiniz.

#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python

Düzenleme : Yalnızca PATH değeri ataması etrafındaki tırnak işaretleri olmadan çalışıyor gibi görünüyor:

#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python

5
Bunun tüm unix varyantlarında çalışmadığını unutmayın (örneğin Linux'ta değil). Ve mevcut tüm dizinleri yoldan kaldırıyorsunuz, bu da çizgide sorunlara yol açıyor.
Gilles 'SO- kötülük' dur

1
PATHBöyle daha iyi genişletmek :PATH=$PATH:/path/to/whatever...
Bengt
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.