Parece-me que os arquivos executam o mesmo sem essa linha.
Parece-me que os arquivos executam o mesmo sem essa linha.
Respostas:
Se você tiver várias versões do Python instaladas, /usr/bin/env
garantirá que o intérprete usado seja o primeiro do seu ambiente $PATH
. A alternativa seria codificar algo como #!/usr/bin/python
; tudo bem, mas menos flexível.
No Unix, um arquivo executável que deve ser interpretado pode indicar qual intérprete deve ser usado com um #!
no início da primeira linha, seguido pelo intérprete (e quaisquer sinalizadores que ele possa precisar).
Se você está falando de outras plataformas, é claro, essa regra não se aplica (mas essa "linha shebang" não faz mal) e ajudará se você copiar esse script para uma plataforma com base em Unix, como Linux, Mac etc).
chmod +x myscript.py
) e depois executando-o diretamente ./myscript.py
:, ao invés de apenas python myscript.py
.
env
fornece flexibilidade máxima, pois o usuário pode selecionar o intérprete a ser alterado, alterando o PATH. Muitas vezes, essa flexibilidade não é necessária e o lado negativo é que o Linux, por exemplo, não pode usar o nome do script para o nome do processo ps
e reverte para "python". Ao empacotar aplicativos python para distribuições, por exemplo, aconselho a não usar env
.
py
O iniciador pode usar a linha shebang no Windows. Está incluído no Python 3.3 ou pode ser instalado independentemente .
/usr/bin/env: Key has expired
depois de muitas horas.
Isso é chamado de linha shebang . Como a entrada da Wikipedia explica :
Na computação, um shebang (também chamado de hashbang, hashpling, pound bang ou crunchbang) refere-se aos caracteres "#!" quando eles são os dois primeiros caracteres em uma diretiva de intérprete como a primeira linha de um arquivo de texto. Em um sistema operacional semelhante ao Unix, o carregador de programa toma a presença desses dois caracteres como uma indicação de que o arquivo é um script e tenta executá-lo usando o interpretador especificado pelo restante da primeira linha do arquivo.
Veja também a entrada de perguntas frequentes do Unix .
Mesmo no Windows, onde a linha shebang não determina o intérprete a ser executado, você pode passar opções para o intérprete especificando-as na linha shebang. Acho útil manter uma linha shebang genérica em scripts únicos (como os que escrevo ao responder perguntas no SO), para que eu possa testá-los rapidamente no Windows e no ArchLinux .
O utilitário env permite chamar um comando no caminho:
O primeiro argumento restante especifica o nome do programa a ser chamado; é pesquisado de acordo com a
PATH
variável de ambiente. Quaisquer argumentos restantes são passados como argumentos para esse programa.
Expandindo um pouco as outras respostas, aqui está um pequeno exemplo de como seus scripts de linha de comando podem ter problemas pelo uso incauto de /usr/bin/env
linhas shebang:
$ /usr/local/bin/python -V
Python 2.6.4
$ /usr/bin/python -V
Python 2.5.1
$ cat my_script.py
#!/usr/bin/env python
import json
print "hello, json"
$ PATH=/usr/local/bin:/usr/bin
$ ./my_script.py
hello, json
$ PATH=/usr/bin:/usr/local/bin
$ ./my_script.py
Traceback (most recent call last):
File "./my_script.py", line 2, in <module>
import json
ImportError: No module named json
O módulo json não existe no Python 2.5.
Uma maneira de se proteger contra esse tipo de problema é usar os nomes de comando python com versão que geralmente são instalados com a maioria dos Pythons:
$ cat my_script.py
#!/usr/bin/env python2.6
import json
print "hello, json"
Se você apenas precisa distinguir entre Python 2.xe Python 3.x, as versões recentes do Python 3 também fornecem um python3
nome:
$ cat my_script.py
#!/usr/bin/env python3
import json
print("hello, json")
which python
retornos /usr/bin/python
, um caminho de diretório local poderia ser codificado: #!/usr/bin/python
. Mas isso é menos flexível do que o #!/usr/bin/env python
que tem uma aplicação global.
Para executar o script python, precisamos dizer ao shell três coisas:
O shebang #!
realiza (1.). O shebang começa com um #
porque o #
personagem é um marcador de comentário em muitas linguagens de script. O conteúdo da linha shebang é, portanto, automaticamente ignorado pelo intérprete.
O env
comando realiza (2.) e (3.). Para citar "grawity",
Um uso comum do
env
comando é iniciar intérpretes, usando o fato de que o env pesquisará $ PATH pelo comando que é solicitado a iniciar. Como a linha shebang exige que um caminho absoluto seja especificado e como a localização de vários intérpretes (perl, bash, python) pode variar muito, é comum usar:
#!/usr/bin/env perl
em vez de tentar adivinhar se é / bin / perl, / usr / bin / perl, / usr / local / bin / perl, / usr / local / pkg / perl, / fileserver / usr / bin / perl ou / home / MrDaniel / usr / bin / perl no sistema do usuário ...Por outro lado, o env está quase sempre em / usr / bin / env. (Exceto nos casos em que não é; alguns sistemas podem usar / bin / env, mas essa é uma ocasião bastante rara e ocorre apenas em sistemas não Linux.)
Talvez sua pergunta seja neste sentido:
Se você deseja usar: $python myscript.py
Você não precisa dessa linha. O sistema chamará python e, em seguida, o interpretador python executará seu script.
Mas se você pretende usar: $./myscript.py
Chamando-o diretamente como um programa normal ou script bash, você precisa escrever essa linha para especificar ao sistema qual programa usar para executá-lo (e também torná-lo executável chmod 755
)
A exec
chamada do sistema do kernel Linux entende shebangs ( #!
) nativamente
Quando você faz no bash:
./something
no Linux, este chama a exec
chamada de sistema com o caminho ./something
.
Essa linha do kernel é chamada no arquivo passado para exec
: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_script.c#L25
if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
Ele lê os primeiros bytes do arquivo e os compara #!
.
Se a comparação for verdadeira, o restante da linha será analisado pelo kernel do Linux, que fará outra exec
chamada com o caminho /usr/bin/env python
e o arquivo atual como o primeiro argumento:
/usr/bin/env python /path/to/script.py
e isso funciona para qualquer linguagem de script que use #
como caractere de comentário.
E sim, você pode fazer um loop infinito com:
printf '#!/a\n' | sudo tee /a
sudo chmod +x /a
/a
O Bash reconhece o erro:
-bash: /a: /a: bad interpreter: Too many levels of symbolic links
#!
por acaso é legível por humanos, mas isso não é necessário.
Se o arquivo exec
fosse iniciado com bytes diferentes, a chamada do sistema usaria um manipulador diferente. O outro manipulador interno mais importante é os arquivos executáveis do ELF: https://github.com/torvalds/linux/blob/v4.8/fs/binfmt_elf.c#L1305, que verifica se há bytes 7f 45 4c 46
(que também são humanos legível para .ELF
). Vamos confirmar que, lendo os 4 primeiros bytes de /bin/ls
, que é um executável ELF:
head -c 4 "$(which ls)" | hd
resultado:
00000000 7f 45 4c 46 |.ELF|
00000004
Portanto, quando o kernel vê esses bytes, ele pega o arquivo ELF, coloca-o na memória corretamente e inicia um novo processo com ele. Veja também: Como o kernel obtém um arquivo binário executável em execução no linux?
Por fim, você pode adicionar seus próprios manipuladores shebang com o binfmt_misc
mecanismo Por exemplo, você pode adicionar um manipulador personalizado para .jar
arquivos . Esse mecanismo ainda suporta manipuladores por extensão de arquivo. Outro aplicativo é executar de forma transparente executáveis de uma arquitetura diferente com o QEMU .
Eu não acho que o POSIX especifique shebangs, no entanto: https://unix.stackexchange.com/a/346214/32558 , embora mencione nas seções de justificativa e na forma "se scripts executáveis são suportados pelo sistema, algo pode acontecer". O macOS e o FreeBSD também parecem implementá-lo.
PATH
busca motivação
Provavelmente, uma grande motivação para a existência de shebangs é o fato de que no Linux, geralmente queremos executar comandos da seguinte PATH
maneira:
basename-of-command
ao invés de:
/full/path/to/basename-of-command
Mas então, sem o mecanismo shebang, como o Linux saberia como iniciar cada tipo de arquivo?
Codificar a extensão nos comandos:
basename-of-command.py
ou implementando a pesquisa PATH em todos os intérpretes:
python basename-of-command
seria uma possibilidade, mas isso tem o grande problema de que tudo quebra se decidirmos refatorar o comando para outro idioma.
Shebangs resolve esse problema lindamente.
Tecnicamente, em Python, isso é apenas uma linha de comentário.
Essa linha é usada apenas se você executar o script py no shell (na linha de comando). Isso é conhecido como " Shebang !" , e é usado em várias situações, não apenas nos scripts Python.
Aqui, ele instrui o shell a iniciar uma versão específica do Python (para cuidar do restante do arquivo.
O principal motivo para fazer isso é tornar o script portátil em ambientes de sistema operacional.
Por exemplo, em mingw, os scripts python usam:
#!/c/python3k/python
e sob a distribuição GNU / Linux, é:
#!/usr/local/bin/python
ou
#!/usr/bin/python
e no melhor sistema comercial Unix sw / hw de todos (OS / X), é:
#!/Applications/MacPython 2.5/python
ou no FreeBSD:
#!/usr/local/bin/python
No entanto, todas essas diferenças podem tornar o script portátil através de todos, usando:
#!/usr/bin/env python
/usr/bin/python
. No Linux, o Python instalado pelo sistema também é quase certamente /usr/bin/python
(nunca vi mais nada e não faria sentido). Observe que pode haver sistemas que não possuem /usr/bin/env
.
python
não é tão portátil, é o interpretador Python padrão de distribuição. Arch Linux padrão para Python 3 por muito tempo e pode distribuições estão pensando sobre isso também, porque Python 2 é suportado somente até 2020.
Provavelmente faz sentido enfatizar uma coisa que a maioria perdeu, o que pode impedir a compreensão imediata. Quando você digita o python
terminal, normalmente não fornece um caminho completo. Em vez disso, o executável é procurado na PATH
variável de ambiente. Por sua vez, quando você deseja executar um programa Python diretamente, /path/to/app.py
deve-se dizer ao shell qual intérprete usar (via hashbang , o que os outros colaboradores estão explicando acima).
Hashbang espera o caminho completo para um intérprete. Portanto, para executar seu programa Python diretamente, você deve fornecer o caminho completo para o binário Python, que varia significativamente, especialmente considerando o uso do virtualenv . Para lidar com a portabilidade, o truque /usr/bin/env
é usado. O último é originalmente destinado a alterar o ambiente no local e executar um comando nele. Quando nenhuma alteração é fornecida, ele executa o comando no ambiente atual, o que resulta efetivamente na mesma PATH
pesquisa que faz o truque.
Esta é uma convenção de shell que informa ao shell qual programa pode executar o script.
#! / usr / bin / env python
resolve um caminho para o binário Python.
É a maneira recomendada, proposta na documentação:
2.2.2 Scripts executáveis em Python
Nos sistemas BSD'ish Unix, os scripts Python podem ser executados diretamente, como shell scripts, colocando a linha
#! /usr/bin/env python3.2
de http://docs.python.org/py3k/tutorial/interpreter.html#executable-python-scripts
Você pode tentar esse problema usando o virtualenv
Aqui está o test.py
#! /usr/bin/env python
import sys
print(sys.version)
Crie ambientes virtuais
virtualenv test2.6 -p /usr/bin/python2.6
virtualenv test2.7 -p /usr/bin/python2.7
ative cada ambiente e verifique as diferenças
echo $PATH
./test.py
Apenas especifica qual intérprete você deseja usar. Para entender isso, crie um arquivo por meio do terminal touch test.py
, e digite o arquivo a seguir:
#!/usr/bin/env python3
print "test"
e faça chmod +x test.py
para tornar seu script executável. Depois disso, ./test.py
você deve receber um erro dizendo:
File "./test.py", line 2
print "test"
^
SyntaxError: Missing parentheses in call to 'print'
porque python3 não suporta o operador de impressão.
Agora vá em frente e altere a primeira linha do seu código para:
#!/usr/bin/env python2
e funcionará, imprimindo test
em stdout, porque python2 suporta o operador de impressão. Então, agora você aprendeu como alternar entre intérpretes de script.
Parece-me que os arquivos executam o mesmo sem essa linha.
Se sim, então talvez você esteja executando o programa Python no Windows? O Windows não usa essa linha; em vez disso, usa a extensão de nome de arquivo para executar o programa associado à extensão de arquivo.
No entanto, em 2011, foi desenvolvido um "iniciador Python" que (até certo ponto) imita esse comportamento do Linux para Windows. Isso se limita apenas à escolha de qual interpretador Python é executado - por exemplo, para selecionar entre Python 2 e Python 3 em um sistema em que os dois estão instalados. O iniciador é opcionalmente instalado como py.exe
pela instalação do Python e pode ser associado aos .py
arquivos, para que o iniciador verifique essa linha e, por sua vez, inicie a versão especificada do interpretador do Python.
$ python myscript.py
.
Isso significa mais informações históricas do que uma resposta "real".
Lembre-se de que antigamente você tinha MUITO UNIX, como sistemas operacionais, cujos designers tinham sua própria noção de onde colocar coisas e, às vezes, não incluíam Python, Perl, Bash ou muitas outras coisas de GNU / Código Aberto . .
Isso aconteceu mesmo com diferentes distribuições Linux. No Linux - pré-FHS [1], você pode ter python em / usr / bin / ou / usr / local / bin /. Ou pode não ter sido instalado, então você construiu o seu próprio e o colocou em ~ / bin
O Solaris foi o pior em que já trabalhei, parcialmente como a transição do Berkeley Unix para o System V. Você pode terminar com coisas em / usr /, / usr / local /, / usr / ucb, / opt / etc. Isso pode fazer com que para alguns realmente caminhos longos. Tenho lembranças das coisas do Sunfreeware.com instalando cada pacote em seu próprio diretório, mas não me lembro se ele vinculou os binários em / usr / bin ou não.
Ah, e algumas vezes o / usr / bin estava em um servidor NFS [2].
Portanto, o env
utilitário foi desenvolvido para solucionar isso.
Então você poderia escrever #!/bin/env interpreter
e, desde que o caminho fosse apropriado, as coisas tinham uma chance razoável de correr. Obviamente, era razoável (para Python e Perl) que você também definisse as variáveis ambientais apropriadas. Para o bash / ksh / zsh, apenas funcionou.
Isso foi importante porque as pessoas estavam passando scripts de shell (como perl e python) e se você codificasse / usr / bin / python na sua estação de trabalho Red Hat Linux, isso seria ruim para um SGI ... bem, não , Acho que o IRIX colocou o python no lugar certo. Mas em uma estação Sparc pode não funcionar.
Sinto falta da minha estação sparc. Mas não muito. Ok, agora você me deixou passeando no E-Bay. Bastagens.
[1] Padrão de hierarquia do sistema de arquivos. https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
[2] Sim, e às vezes as pessoas ainda fazem coisas assim. E não, eu não usava nem nabo nem cebola no cinto.
Se você estiver executando seu script em um ambiente virtual, por exemplo venv
, a execução which python
durante o trabalho venv
exibirá o caminho para o interpretador Python:
~/Envs/venv/bin/python
Observe que o nome do ambiente virtual está incorporado no caminho para o interpretador Python. Portanto, a codificação desse caminho no seu script causará dois problemas:
Portanto, para adicionar à resposta de Jonathan , o shebang ideal é #!/usr/bin/env python
, não apenas para portabilidade entre sistemas operacionais, mas também para portabilidade em ambientes virtuais!
Considerando os problemas de portabilidade entre python2
e python3
, você sempre deve especificar uma das versões, a menos que seu programa seja compatível com ambas.
Algumas distribuições são frete python
ligada simbolicamente a python3
por um tempo agora - não dependem de python
serpython2
.
Isso é enfatizado pelo PEP 394 :
Para tolerar diferenças entre plataformas, todo o novo código que precisa chamar o interpretador Python não deve especificar python, mas sim especificar python2 ou python3 (ou as versões mais específicas python2.xe python3.x; consulte as Notas sobre migração ) . Essa distinção deve ser feita em shebangs, ao invocar a partir de um script de shell, ao invocar através da chamada system () ou ao invocar em qualquer outro contexto.
Permite selecionar o executável que você deseja usar; o que é muito útil se você tiver várias instalações python e módulos diferentes em cada uma delas e desejar escolher. por exemplo
#!/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 $ALTERNATIVE_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())
isto diz ao script onde está o diretório python!
#! /usr/bin/env python
#!/usr/bin/env python
na parte superior.