Devo colocar #! (shebang) nos scripts Python, e que forma deve ser?

830

Devo colocar o shebang nos meus scripts Python? De que forma?

#!/usr/bin/env python 

ou

#!/usr/local/bin/python

Estes são igualmente portáteis? Qual formulário é mais usado?

Nota: oprojeto tornado usa o shebang. Por outro lado, oprojeto Django não.

codificador de árvore
fonte
70
O segundo não é portátil e irá falhar em muitos computadores, se não a maioria.
Dietrich Epp
4
Como se #!/usr/bin/pythoncompara à primeira opção? Eu vejo isso em muitos exemplos de código. Edit: Talvez esta é a resposta .. stackoverflow.com/a/2429517/1156245
geotheory
1
Eu digo sempre use-o, por quê? "Zen Of Python" - Linha 2 - "Explícito é melhor que implícito." python.org/dev/peps/pep-0020
JayRizzo
2
Francamente, nenhum dos dois está "certo", porque você, como autor, não sabe onde estará a versão correta do Python quando o script for executado. Deve ser o trabalho do instalador adicionar o shebang correto.
chepner

Respostas:

1117

A linha shebang em qualquer script determina a capacidade do script de ser executado como um executável independente sem digitar pythonpreviamente no terminal ou ao clicar duas vezes nele em um gerenciador de arquivos (quando configurado corretamente). Não é necessário, mas geralmente é colocado lá. Quando alguém vê o arquivo aberto em um editor, ele imediatamente sabe o que está vendo. No entanto, qual linha de shebang você usa É importante.

O uso correto para scripts Python 3 é:

#!/usr/bin/env python3

O padrão é a versão 3.latest. Para o Python 2.7.latest use python2no lugar de python3.

O seguinte NÃO deve ser usado (exceto no caso raro de você estar escrevendo código compatível com o Python 2.xe 3.x):

#!/usr/bin/env python

A razão para essas recomendações, dada no PEP 394 , é que pythonpode se referir a python2ou python3em sistemas diferentes. Atualmente, ele se refere à python2maioria das distribuições, mas é provável que isso mude em algum momento.

Além disso, NÃO use:

#!/usr/local/bin/python

"python pode ser instalado em / usr / bin / python ou / bin / python nesses casos, o #! acima falhará."

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

GlassGhost
fonte
4
@EliasVanOotegem Se você não pode ter certeza de que o python será encontrado /usr/bin, como pode ter certeza de que envserá encontrado no /usr/bin. Se o python estiver instalado em um local não padrão, isso provavelmente significa que o python está configurado de maneira não padrão e que o script deve falhar rapidamente como resultado. Em vez de fazer suposições sobre as propriedades do intérprete python e esperar o melhor.
Dunes
65
@Dunes: envvai sempre ser encontrada em /usr/bin/, e seu trabalho é para localizar caixas (como python) usando PATH. Não importa como o python esteja instalado, seu caminho será adicionado a essa variável e envo encontrará (caso contrário, o python não está instalado). Esse é o trabalho env, essa é toda a razão pela qual ela existe. É o que alerta o ambiente (configure variáveis ​​env, incluindo os caminhos de instalação e inclua caminhos). As pessoas sempre entenderam que esse comando só pode funcionar se for sempre encontrado no mesmo local. Isso é apenas um dado
Elias Van Ootegem
3
@JFSebastian: Você está certo, não é garantido ou aplicado pelo padrão POSIX. Supus que fosse porque uma das versões posteriores do IEEE continha algumas coisas do ambiente. De qualquer maneira: não, /usr/bin/envnão é garantido por qualquer padrão, além de uma ampla (universalmente?) Regra adotada ...
Elias Van Ootegem
6
Se você estiver usando o virtualenv, #! / Usr / local / bin / python, mesmo que exista, erra.
Null
6
Um problema com isso: de acordo com o PEP394, deve-se usar o pythonexecutável apenas quando o script é compatível com Python 2 e Python 3. Caso contrário, ele deve apontar para a escolha apropriada de python2e python3.
precisa saber é o seguinte
67

É realmente apenas uma questão de gosto. Adicionar o shebang significa que as pessoas podem invocar o script diretamente, se quiserem (assumindo que seja marcado como executável); omitir apenas significa pythonque deve ser invocado manualmente.

O resultado final da execução do programa não é afetado de qualquer maneira; são apenas opções dos meios.

Âmbar
fonte
3
É isso mesmo - não importa de que lado você fica, porque não existe um lado "certo". É uma decisão completamente subjetiva.
Amber
5
Não mais do que qualquer outra decisão trivial. en.wikipedia.org/wiki/Parkinson's_Law_of_Triviality
Amber
2
Como eu poderia executar um arquivo python diretamente sem o comando 'python'?
Zen
5
@Zen Supondo que você incluiu o shebang (#! / Usr / bin / env python) em seu script, você só precisa tornar seu script executável. Algo como chmod a+x [your-script].pydeve torná-lo executável e então você pode simplesmente chamar ./[your-script.py]no shell.
Skoklfyfan
9
Como a resposta por GlassGhost assinala, não é uma vantagem concreta para incluí-lo além gosto: ele deixa claro para um futuro leitor do arquivo que eles estão lendo um script executável, em vez de um arquivo que está destinado a ser importado. Da mesma forma que os modificadores de controle de acesso público / privado nos idiomas que os possuem, os shebangs são úteis como documentação e também para seus efeitos reais e, em alguns casos, o aspecto da documentação realmente é mais importante.
Mark Amery
32

Devo colocar o shebang nos meus scripts Python?

Coloque um shebang em um script Python para indicar:

  • este módulo pode ser executado como um script
  • se ele pode ser executado apenas em python2, python3 ou é compatível com Python 2/3
  • no POSIX, é necessário se você deseja executar o script diretamente sem chamar pythonexplicitamente o executável

Estes são igualmente portáteis? Qual formulário é mais usado?

Se você escrever um shebang manualmente , use-o sempre, a #!/usr/bin/env pythonmenos que tenha um motivo específico para não usá-lo. Este formulário é entendido até no Windows (iniciador do Python).

Nota: os scripts instalados devem usar um executável python específico, por exemplo, /usr/bin/pythonou /home/me/.virtualenvs/project/bin/python. É ruim se alguma ferramenta quebrar se você ativar um virtualenv no seu shell. Felizmente, o shebang correto é criado automaticamente na maioria dos casos por setuptoolssuas ferramentas de pacote de distribuição (no Windows, setuptoolspode gerar .exescripts de wrapper automaticamente).

Em outras palavras, se o script estiver em uma verificação de origem, você provavelmente verá #!/usr/bin/env python. Se estiver instalado, o shebang é o caminho para um executável python específico, como #!/usr/local/bin/python (NOTA: você não deve escrever os caminhos da última categoria manualmente).

Para escolher se você deve usar python, python2ou python3no shebang, consulte PEP 394 - O comando "python" em sistemas similares a Unix :

  • ... pythondeve ser usado na linha shebang apenas para scripts compatíveis com a origem do Python 2 e 3.

  • na preparação para uma eventual alteração na versão padrão do Python, apenas os scripts do Python 2 devem ser atualizados para serem compatíveis com a origem do Python 3 ou para serem usados python2na linha shebang.

jfs
fonte
3
A primeira resposta para até se referir a um PEP não tem votos suficientes. Hã? Existe um PEP para #!/usr/bin/env pythonsi?
binki 24/09/2015
Por favor não use #!/usr/bin/env python. Por favor, não sugira "sempre use" #!/usr/bin/env python. É a coisa errada a fazer em 99% dos casos (o motivo que você incluiu na sua resposta).
Jay Sullivan
1
@JaySullivan você entende a diferença entre um checkout de origem e os scripts instalados? Eu estou por trás da sugestão. Isso funciona bem.
JFS
1
@jfs: Depois de reler meu comentário, vejo como não consegui entender meu ponto de vista. O que eu quis dizer foi que a maioria das pessoas vai querer usar 'python2' ou 'python3', não 'python'. Seja para resolver ou não via caminho completo ou env, que tecnicamente era a questão do OP, você respondeu e eu não discordo sobre esse ponto.
Jay Sullivan
@JaySullivan, eu concordo. Você leu a citação do pep na resposta. Diz a mesma coisa.
JFS
15

Se você possui mais de uma versão do Python e o script precisa ser executado em uma versão específica, o she-bang pode garantir que a correta seja usada quando o script for executado diretamente, por exemplo:

#!/usr/bin/python2.7

Observe que o script ainda pode ser executado por meio de uma linha de comando completa do Python ou por importação, nesse caso o she-bang é ignorado. Mas para scripts executados diretamente, esse é um motivo decente para usar o she-bang.

#!/usr/bin/env python geralmente é a melhor abordagem, mas isso ajuda em casos especiais.

Geralmente, seria melhor estabelecer um ambiente virtual Python; nesse caso, o genérico #!/usr/bin/env pythonidentificaria a instância correta do Python para o virtualenv.

Chris Johnson
fonte
O espaço não fará com que ele falhe?
RandomInsano 28/01
1
@RandomInsano, acho que não. Os espaços parecem bastante comuns e há muitas evidências em torno da rede como um uso aceito. No entanto, acho que o espaço não é provavelmente o uso mais canônico.
Chris Johnson
1
Você está definitivamente certo neste. Apenas testado em bash e tcsh.
RandomInsano 30/01
Os resultados whichfornecerão uma string que funcionará, ponto final. Você não precisa se preocupar com nenhuma das tripas para usá-lo.
SDSolar 17/10
10

Você deve adicionar um shebang se o script tiver a intenção de ser executável. Você também deve instalar o script com um software de instalação que modifique o shebang para algo correto, para que ele funcione na plataforma de destino. Exemplos disso são distutils e Distribute.

Lennart Regebro
fonte
1
Você não precisa modificar o #! linha depois. É para isso que serve o / usr / bin / env. A codificação embutida em um intérprete Python específico pode fazer mais mal do que bem. É muito frágil em relação à instalação de outra versão do Python ou alternar entre o Python da nossa distribuição e uma instalação personalizada do Python.
vog 31/01
No Ubuntu, o uso dos resultados de whichescolherá automaticamente o padrão que está sendo usado pelos comandos do sistema e tal. É genérico e o sistema o direciona para a instalação correta.
SDsolar
9

O objetivo do shebang é que o script reconheça o tipo de intérprete quando você deseja executar o script a partir do shell. Principalmente, e nem sempre, você executa scripts fornecendo o intérprete externamente. Exemplo de uso:python-x.x script.py

Isso funcionará mesmo se você não tiver um declarador shebang.

Por que o primeiro é mais "portátil" é porque /usr/bin/envcontém o seuPATH declaração que responde por todos os destinos em que os executáveis ​​do sistema residem.

NOTA: O Tornado não usa estritamente shebangs e o Django estritamente não. Isso varia de acordo com a maneira como você está executando a função principal do seu aplicativo.

TAMBÉM: Não varia com o Python.

meson10
fonte
8

Às vezes, se a resposta não for muito clara (quero dizer, você não pode decidir se sim ou não), isso não importa muito e você pode ignorar o problema até que a resposta seja clara.

O #!único objetivo é iniciar o script. O Django carrega os fontes por conta própria e os utiliza. Ele nunca precisa decidir qual intérprete deve ser usado. Dessa forma, o#! realmente não faz sentido aqui.

Geralmente, se é um módulo e não pode ser usado como um script, não há necessidade de usar o #!. Por outro lado, uma fonte de módulo geralmente contém if __name__ == '__main__': ...pelo menos alguns testes triviais da funcionalidade. Então o#! faz sentido novamente.

Uma boa razão para usar #!é quando você usa os scripts Python 2 e Python 3 - eles devem ser interpretados por diferentes versões do Python. Dessa forma, você deve se lembrar do que pythondeve ser usado ao iniciar o script manualmente (sem o #!interior). Se você tiver uma mistura desses scripts, é uma boa ideia usar o #!interior, torná-los executáveis ​​e iniciá-los como executáveis ​​(chmod ...).

Ao usar o MS-Windows, o #!não tinha sentido - até recentemente. O Python 3.3 apresenta um Iniciador do Windows Python (py.exe e pyw.exe) que lê a #!linha, detecta as versões instaladas do Python e usa a versão correta ou explicitamente desejada do Python. Como a extensão pode ser associada a um programa, você pode obter um comportamento semelhante no Windows e com o sinalizador de execução em sistemas baseados em Unix.

pepr
fonte
3

Quando instalei o Python 3.6.1 no Windows 7 recentemente, ele também instalou o Python Launcher para Windows, que deve lidar com a linha shebang. No entanto, descobri que o Python Launcher não fazia isso: a linha shebang era ignorada e o Python 2.7.13 sempre era usado (a menos que eu executasse o script usando py -3).

Para corrigir isso, tive que editar a chave de registro do Windows HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.File\shell\open\command. Isso ainda tinha o valor

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

da minha instalação anterior do Python 2.7. Eu modifiquei esse valor da chave do registro para

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

e o processamento de linha shebang do Python Launcher funcionou como descrito acima.

ETalbot
fonte
2

Se você possui módulos diferentes instalados e precisa usar uma instalação python específica, o shebang parece estar limitado primeiro. No entanto, você pode fazer truques como o abaixo para permitir que o shebang seja chamado primeiro como um script de shell e, em seguida, escolha python. Isso é muito flexível:

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

Ou melhor ainda, talvez, para facilitar a reutilização de código em vários scripts python:

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

e então select.sh possui:

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
Neil McGill
fonte
1
Embora eu não tenha certeza de que um poliglota como esse seja uma boa prática em geral, é certamente uma abordagem muito interessante e provavelmente a resposta mais flexível aqui.
Ryan Amos
1
Muito legal. Eu não sabia que você poderia fazer isso
user2233949 29/04
1

Resposta: Somente se você planeja torná-lo um script executável da linha de comandos.

Aqui está o procedimento:

Comece verificando a string shebang apropriada para usar:

which python

Pegue a saída disso e adicione-a (com o shebang #!) Na primeira linha.

No meu sistema, ele responde da seguinte maneira:

$which python
/usr/bin/python

Portanto, seu shebang terá a seguinte aparência:

#!/usr/bin/python

Após salvar, ele ainda será executado como antes, pois o python verá a primeira linha como um comentário.

python filename.py

Para torná-lo um comando, copie-o para soltar a extensão .py.

cp filename.py filename

Diga ao sistema de arquivos que isso será executável:

chmod +x filename

Para testá-lo, use:

./filename

A melhor prática é movê-lo para algum lugar do seu $ PATH, para que você só precise digitar o nome do arquivo.

sudo cp filename /usr/sbin

Dessa forma, ele funcionará em qualquer lugar (sem o ./ antes do nome do arquivo)

SDsolar
fonte
Duvido que essa seja uma boa prática e recomendo fortemente o uso da solução GlassGhost .
Colidyre 25/06/19
Achei isso útil e funcionou muito bem para mim. isso foi bem explicado. Eu apreciaria comentários indicando por que essa não é uma prática recomendada, no entanto. Estou ansioso para aprender.
Charles Carriere
0

Caminho absoluto x caminho lógico:

Esta é realmente uma pergunta sobre se o caminho para o interpretador Python deve ser absoluto ou Logical ( /usr/bin/env) em relação à portabilidade.

Encontrando outras respostas neste e em outros sites da Stack que falaram sobre o problema de uma maneira geral, sem provas de suporte, realizei alguns testes e análises realmente, REALMENTE , granulares nesta mesma questão no unix.stackexchange.com . Em vez de colar a resposta aqui, apontei os interessados ​​para a análise comparativa para essa resposta:

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

Sendo um engenheiro de Linux, meu objetivo é sempre fornecer os hosts mais adequados e otimizados para meus clientes desenvolvedores; portanto, a questão dos ambientes Python era algo para o qual eu realmente precisava de uma resposta sólida. Minha opinião após o teste foi que o caminho lógico no she-bang era a melhor das (2) opções.

F1Linux
fonte
-3

Use primeiro

which python

Isso fornecerá a saída como o local em que meu interpretador python (binário) está presente.

Essa saída pode ser qualquer

/usr/bin/python

ou

/bin/python

Agora selecione apropriadamente a linha shebang e use-a.

Para generalizar, podemos usar:

#!/usr/bin/env

ou

#!/bin/env
frp farhan
fonte
3
Provavelmente, isso não será portátil para outros sistemas. #!/usr/bin/envfaz a escolha certa para você.
Fragmentedreality
É por isso que você usa o whichcomando - ele retornará a string correta para o seu sistema específico.
SDsolar
1
... e, em seguida, cada vez que o script será executado em outra máquina, você corre which pythonnovamente e alterar o script se os difere de saída do shebang atual
fragmentedreality
2
-1 Esta é a solução mais frágil possível. Só é garantido que ele esteja correto para o sistema no qual seu script python está gravado. Use #! / Usr / bin / env python3 para portabilidade
Myles Hollowed