Eu tenho um script Python que precisa ser executado com uma instalação python específica. Existe uma maneira de criar um shebang para que ele funcione $FOO/bar/MyCustomPython
?
Eu tenho um script Python que precisa ser executado com uma instalação python específica. Existe uma maneira de criar um shebang para que ele funcione $FOO/bar/MyCustomPython
?
Respostas:
A linha shebang é muito limitada. Sob muitas variantes do unix (incluindo Linux), você pode ter apenas duas palavras: um comando e um único argumento. Também há frequentemente uma limitação de comprimento.
A solução geral é escrever um pequeno invólucro de casca. Nomeie o script Python foo.py
e coloque o shell script ao lado foo.py
e chame-o 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 descrito acima e colocar #!/path/to/wrapper/script
como a linha shebang no script Python. No entanto, a maioria dos unices não suporta encadeamento de scripts shebang, portanto, isso não funcionará.
Se MyCustomPython
estava no $PATH
, você pode usar env
para procurar:
#!/usr/bin/env MyCustomPython
import …
Outra abordagem é organizar para que o script seja um script shell válido (que carrega o interpretador Python correto 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 dois idiomas para o seu idioma de destino. No 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 true
utilitário, que ignora seus argumentos (duas cadeias de caracteres únicos :
e '
) e retorna um valor verdadeiro. No Python, "true"
é uma string que é verdadeira quando interpretada como booleana; portanto, esta é uma if
instrução que é sempre verdadeira e executa uma literal de string.
#!/bin/sh
if "true" : '''\'
then
exec "$FOO/bar/MyCustomPython" "$0" "$@"
exit 127
fi
'''
import …
O código Rosetta possui scripts de dois idiomas em vários outros idiomas.
PYTHONPATH
variável env para carregar módulos de um local não padrão para um script CGI em um sistema ao qual não tinha acesso root. Poupança de vida. Obrigado novamente.
As linhas Shebang não sofrem expansão variável; portanto, você não pode usá- $FOO/MyCustomPython
lo, pois ele procuraria por um executável chamado dollar-FOO -...
Uma alternativa é fazer com que seu shebang aponte para um script de shell como intérprete, e esse script de shell pode usar variáveis de ambiente para localizar o correto e executá-lo.
Exemplo: crie um mypython.sh
script /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 executar um script Python MyCustomPython
através de mypython.sh
:
#!/usr/bin/env mypython.sh
$python
, não $PYTHON
por convenção, capitalizamos variáveis de ambiente (PAGER, EDITOR, SHELL ... $PYTHON
em seu script não é uma variável de ambiente) e variáveis internas do shell (BASH_VERSION, RANDOM, ...). Todos os outros nomes de variáveis devem conter pelo menos uma letra minúscula. Esta convenção evita a substituição acidental de variáveis ambientais e internas. Além disso, não use extensões para seus scripts. Os scripts definem novos comandos que você pode executar, e os comandos geralmente não recebem extensões.
Você pode usar o caminho absoluto para a instalação customizada do python ou pode colocá-lo no seu $PATH
e use #!/usr/bin/env [command]
. Caso contrário, escreva um wrapper para ele e use-o exec
para substituir a imagem do processo, como um exemplo:
#!/bin/bash
exec "$ENV/python" "$@"
Primeiro, determine como a sua versão do Python é diferente do Python padrão 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. Faço algo semelhante para uma instância com a biblioteca sql interna que não pode ser importada como um módulo no python do sistema.
Se você pode substituir $FOO
por $FOO/bar/MyCustomPython
opções de caminho concreto, pode dizer à env
linha shebang onde procurar sua versão personalizada do Python, definindo diretamente um personalizado PATH
.
#!/usr/bin/env PATH="/path1/to/MyCustomPython:/path2/to/MyCustomPython" python
Editar : parece funcionar apenas sem aspas na atribuição de valor PATH:
#!/usr/bin/env PATH=/path1/to/MyCustomPython:/path2/to/MyCustomPython python
PATH
assim:PATH=$PATH:/path/to/whatever...