Como posso usar variáveis de ambiente na minha shebang?

30

Eu tenho um script Python que precisa ser executado com uma instalação específica do python. Existe uma maneira de criar um shebang para que ele seja executado com $FOO/bar/MyCustomPython ?

    
por eric.frederich 16.09.2011 / 20:06

5 respostas

26

A linha shebang é muito limitada. Sob muitas variantes unix (incluindo o Linux), você pode ter apenas duas palavras: um comando e um único argumento. Há também muitas vezes uma limitação de comprimento.

A solução geral é escrever um pequeno invólucro de shell. Nomeie o script Python foo.py e coloque o script de shell ao lado de foo.py e chame-o de foo . Essa abordagem não requer nenhum cabeçalho específico no script Python.

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

Outra abordagem tentadora é escrever um script wrapper como o acima e colocar #!/path/to/wrapper/script como a linha shebang no script Python. No entanto, a maioria dos unices não suporta o encadeamento de scripts shebang, então isso não funcionará.

Se MyCustomPython estivesse no $PATH , você poderia usar env para pesquisá-lo:

#!/usr/bin/env MyCustomPython
import …

Ainda outra abordagem é organizar o script para ser tanto um script de shell válido (que carrega o interpretador Python em si mesmo) e um script válido na linguagem de destino (aqui Python). Isso requer que você encontre uma maneira de escrever um script em duas línguas para o idioma de destino. Em Perl, isso é conhecido como if $running_under_some_shell .

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

Aqui está uma maneira de obter o mesmo efeito no Python. No shell, "true" é o utilitário true , que ignora seus argumentos (duas sequências de caracteres únicos : e ' ) e retorna um valor verdadeiro. Em Python, "true" é uma string que é verdadeira quando interpretada como booleana, portanto, essa é uma instrução if que é sempre verdadeira e executa uma string literal.

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

O código da Rosetta tem esses scripts de idioma duplo em vários outros idiomas.

    
por 17.09.2011 / 02:03
12

As linhas do Shebang não passam por expansão variável, portanto você não pode usar $FOO/MyCustomPython como ele procuraria por um executável chamado dollar-F-O-O -...

Uma alternativa é fazer com que o seu shebang aponte para um script de shell como o interpretador, e este script de shell pode então usar variáveis de ambiente para localizar o correto e executá-lo.

Exemplo: crie um script mypython.sh em /usr/local/bin (ou qualquer outro diretório no seu $PATH ), com o seguinte conteúdo:

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

então você pode usar esta linha shebang para ter um script Python executado através de MyCustomPython via mypython.sh :

#!/usr/bin/env mypython.sh
    
por 16.09.2011 / 20:18
4

Você pode usar o caminho absoluto para a instalação personalizada do python ou pode colocá-lo em $PATH e usar #!/usr/bin/env [command] . Caso contrário, escreva um wrapper para ele e use exec para substituir a imagem do processo, como um exemplo:

#!/bin/bash
exec "$ENV/python" "$@"
    
por 16.09.2011 / 20:16
3

Primeiro, determine como sua versão do Python é diferente do padrão Python já instalado (por exemplo, um módulo adicional) e, em seguida, no início do programa, 'switch', como o Python é chamado:

#!/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

Isso deve permitir que o programa seja chamado por qualquer outra instância do Python. Eu faço algo semelhante para uma instância com biblioteca sql interna que não pode ser importada como um módulo no python do sistema.

    
por 16.09.2011 / 20:49
0

Se você puder substituir $FOO em $FOO/bar/MyCustomPython por opções de caminhos concretos, poderá informar à linha env shebang onde procurar sua versão personalizada do Python definindo diretamente um PATH personalizado nela.

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

Editar : parece funcionar apenas sem aspas em torno da atribuição de valor PATH:

#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
    
por 17.09.2011 / 16:06