Por que o Python no Linux requer a linha #! / Usr / bin / python?

50

Pergunta bastante simples: no Linux, por que o Python requer a linha

#!/usr/bin/python

no início de um arquivo python, já que o Windows não funciona?

O que isso faz? porque a descrição "Links para Python" é um pouco vaga ...

Diga-me o porquê
fonte
28
As respostas abaixo estão corretas, nenhuma delas aborda por que o Windows não precisa dessa linha. O Windows depende da extensão do arquivo (a parte após .) para determinar que tipo de arquivo é. Até o Windows está se afastando disso: examine as primeiras linhas do arquivo do Microsoft Word e ele indicará que é de fato um arquivo do Microsoft Word.
Charles Green
9
O elefante na sala é que você NUNCA deve usar / usr / bin / python, a menos que seja compatível com o python 2 e 3. Motivo: o arch o vincula ao python3, um movimento que é reconhecido pelo PSF, que o recomenda.
Outro usuário
5
Está implícito, mas não declarado explicitamente nas respostas abaixo que não é necessário . É necessário se você deseja executar o script apenas com o seu próprio nome. Você sempre pode executar python myscript.py.
Chris H
3
@CharlesGreen, não devemos saber por que o Windows não ;-) Isso é SO.
Rinzwind
2
@YetAnotherUser Já se passaram seis anos e onze meses desde o lançamento do Python 3, neste ponto, acho que as pessoas estariam melhor sem o padrão 3 e especificando explicitamente o uso de 2 quando necessário.
JAB

Respostas:

58

O Python não possui nenhum requisito especial no Linux. É o carregador de programa no Unix / Linux que usa a linha "shebang", como é chamada. Este é realmente um recurso, e não uma limitação, mas chegaremos a isso em um momento. A página do wiki em "shebang" tem mais detalhes, mas tentarei dar uma visão geral e uma comparação com o Windows aqui.

Primeiro, vejamos a situação no Windows:

  • Quando você tenta abrir ou executar um arquivo, o Windows examina primeiro a extensão desse arquivo. Esta é a última parte do nome do arquivo iniciada por .No caso de arquivos Python, normalmente é .py.
  • O Windows consulta as ações a serem tomadas com base na extensão do arquivo.
    • Esta informação é registrada no registro do Windows; quando o Python é instalado, normalmente informa ao Windows que os .pyarquivos devem ser abertos usando o aplicativo Python recém-instalado (ou seja, o interpretador Python).
    • Vários tipos de arquivo têm comportamentos internos; por exemplo, arquivos executáveis ​​(como o próprio interpretador Python) devem terminar .exee os .batarquivos são executados como scripts em lote do Windows.
    • A ação executada para um tipo de arquivo específico é personalizável . Você pode, por exemplo, informar ao Windows que, em vez de executar .pyarquivos usando python.exe, ele deve abri-los com outro programa, como o editor de texto notepad.exe.
      • Nesse caso, para executar um script Python, você precisará chamar manualmentepython <scriptname>.py (ou escrever um .batarquivo para fazer isso por você).

Agora, o que acontece se houver uma linha shebang ( #!/usr/bin/pythonou #!/usr/bin/env python) na parte superior do script Python? Bem, como #é uma linha de comentário no Python, o intérprete do Python simplesmente a ignora. Essa é uma das razões pelas quais a maioria das linguagens de script usadas no mundo Unix / Linux usa #para iniciar linhas de comentários.

Portanto, é um pouco enganador dizer que o Windows "não precisa" da #!linha; O Windows não a #!linha e, de fato, depende da extensão do arquivo para dizer o que fazer. Isso tem algumas desvantagens:

  • Você deve nomear os scripts Python .pyno final para que sejam reconhecidos automaticamente como tal.
  • Não há uma maneira fácil de distinguir scripts Python2 de scripts Python3.
  • Como observado anteriormente, se você alterar o comportamento de inicialização padrão para o .pytipo de arquivo, o Windows não executará mais automaticamente esses scripts com o Python. Observe que isso pode ser feito sem intenção.

Agora, vamos ver como o Unix / Linux lança scripts:

A primeira coisa a observar é que o Unix / Linux, ao contrário do Windows, não está tentando "abrir" scripts Python usando um programa específico, pelo menos conceitualmente; o SO sabe que o script é algo que pode ser executado devido a algo chamado "bit de execução" (que está fora do escopo desta resposta). Portanto, se você digitar acidentalmente em #!/usr/bin/pthonvez de #!/usr/bin/python, receberá uma mensagem de erro que inclui este texto:

/usr/bin/pthon: bad interpreter: No such file or directory.

A palavra "intérprete" nos dá uma pista sobre o papel da linha shebang (embora tecnicamente o programa especificado possa ser algo diferente de um intérprete, como catum editor de texto). Quando você tenta executar um arquivo, eis o que acontece:

  • O carregador de programa Unix / Linux analisa os dois primeiros bytes desse arquivo; se esses dois bytes forem #!, o carregador interpretará o restante da linha shebang (excluindo o próprio shebang) como um comando para iniciar um intérprete com o qual executar o conteúdo do arquivo como um script.
  • O carregador de programa inicia o intérprete especificado, alimentando-o como um argumento do caminho do arquivo original.

Isso tem algumas vantagens:

  • O gravador de script tem mais controle sobre qual intérprete será usado (o que soluciona o problema do Python2 / Python3) e, às vezes, pode passar um argumento extra para o intérprete (consulte a página Wiki para obter detalhes).
  • O nome do arquivo do script é ignorado , para que você possa nomear os scripts Python como desejar.

Observe, finalmente, que o Unix / Linux não precisa da linha shebang para executar um script Python. Lembre-se de que tudo o que a linha shebang realmente faz é permitir que o carregador do programa selecione um intérprete. Mas, assim como no Windows, isso pode ser feito manualmente:

python <myscript>
Kyle Strand
fonte
11
No Windows, você pode facilmente ter .py2e .py3extensões para scripts Python 2 / Python 3. Portanto, o Linux (+ x bit) e o Windows (extensão de arquivo) precisam de metadados no sistema de arquivos. A principal diferença é que o bit + x é mais facilmente perdido no trânsito. Isso não é necessariamente uma desvantagem.
MSalters
11
@MSalters O bit de execução também possui muito menos informações codificadas. E observe que você pode ter vários intérpretes Python2 em um determinado sistema (houve uma situação semelhante com Ruby e outras linguagens em um trabalho anterior meu); lidar com isso através da linha shebang é quase trivial, enquanto a situação no Windows fica substancialmente menos tratável quanto mais você tenta gerenciar vários tipos de arquivos semelhantes.
Kyle Strand
Além disso, a extensão realmente conta como "metadados"? É apenas parte do nome do arquivo.
Kyle Strand
11
Os metadados de um arquivo incluem o nome do arquivo inteiro, a hora da criação, os bits de acesso etc. Somente o conteúdo em si é dado em vez de metadados. Quanto aos "múltiplos intérpretes", esse é realmente um problema real e exatamente por que não deveria estar na linha do shebang. E se você tiver /usr/bin/i686/pythone /usr/bin/amd64/python? Perfeitamente razoável, mas quebra os scripts python que têm uma suposição codificada /usr/bin/python. A escolha do intérprete não é do escritor do script, mas do usuário do script. O escritor do script apenas escolhe o idioma (dialeto).
MSalters
11
@MSalters Bem, /usr/bin/envé para isso que serve, juntamente com scripts de configuração de ambiente. Qual é a versão do Windows para isso? Executando um regeditscript antes de iniciar um .pyarquivo para garantir que você obtenha o intérprete desejado?
Kyle Strand
41

A linha que você indicou é usada para informar ao computador qual programa / intérprete usar ao executar o arquivo / script diretamente e quaisquer argumentos que devem ser passados ​​para esse programa quando o script for executado. Entretanto, este não é um requisito do Python , é um requisito do kernel / sistema do linux se você deseja executar o script diretamente (e não passá-lo ao Python pela sintaxe abaixo).

Não é necessário se você deseja executar python script.pyou algo semelhante. Isso é necessário apenas se você deseja executar o script / arquivo diretamente, sem fornecer também o intérprete para usar (como python).


Para um script Bash, teria algo como isto:

#!/bin/bash [optional Bash arguments]
# Bash script code here
...
exit 0;

Isso indicaria ao sistema que, quando isso for executado, ele deverá ser executado por meio de /bin/bashqual é uma das linguagens de shell / shell-script do sistema.


Para o código Python, no entanto, aqui, você desejará que o arquivo executável seja executado via Python, então você diz qual intérprete você pretende executar nele.

#!/usr/bin/python [optional Python arguments]
# Python code here
...
exit()

Isso, como no Bash, indica que /usr/bin/pythondeve ser usado (provavelmente é Python 2 ou Python 3, dependendo das configurações individuais do sistema).


Dessa forma, você pode executar ./filename.pyou ./executableou ./scripttorundiretamente.

Sem essa linha no início, e assumindo que você configurou o arquivo / script para ser executável, e assumindo que você está trabalhando com um script Python, você teria que executar python filename.pyou semelhante se não tivesse a #!/usr/bin/pythonlinha. (Para um script Bash, você precisaria fazer bash script.sh, ou semelhante, para outros scripts / idiomas, como Perl, Ruby, etc.)

O destaque da sintaxe acima é específico do idioma em cada seção, embora isso realmente não importe.

Thomas Ward
fonte
11
Uma coisa interessante para adicionar seria que é possível especificar parâmetros adicionais após o próprio shebang, na maioria dos casos, da mesma forma como se o intérprete foi chamado diretamente ( #!/bin/bash -x, #!/usr/bin/perl -lan, etc).
kos
7
@ kos: Eu acho que você pode especificar exatamente um argumento extra, que tem sido uma PITA quando alguém (deveria) usar /usr/bin/env pythonpara obter o python correto.
usar o seguinte
@progo Não sei ao certo qual é o problema env, mas o problema parece não ser o número de argumentos: #!/usr/bin/perl -l -a -npossui três argumentos, mas funciona. Mais uma vez, não consigo entender o problema exato.
kos
Ao chamar explicitamente um intérprete com o script como argumento, não há razão para começar com o último ./. Em outras palavras, apenas python filename.pyou bash script.shirá funcionar bem. O único motivo para incluir ./está no nome de um comando, quando você deseja informar ao shell para não pesquisar $PATH(o que provavelmente não encontrará arquivos no diretório atual), mas seguir o caminho especificado como está. Mas isso não se aplica a argumentos de comando.
21415 Marc Jacqueline
@ kos: O problema pode estar em como envrecebe o restante dos argumentos do kernel. Presume-se que todos eles sejam um grande argumento sem que a divisão por espaço seja realizada. Desculpe de articulação, não me lembro os detalhes deste que bem mais
unperson325680
16

A linha:

#!/usr/bin/python

é chamado de 'shebang' e indica o caminho para o binário do interpretador que será usado para interpretar o restante dos comandos no arquivo. Geralmente é a primeira linha de um script.

Portanto, a linha #!/usr/bin/pythonindica que o conteúdo do arquivo será interpretado pelo pythonbinário localizado em /usr/bin/python.

Observe que a linha shebang é analisada pelo kernel e, em seguida, o script será chamado como argumento:

python script_name

Da mesma forma, no caso de #!/bin/bash:

bash script_name
heemail
fonte
2
Acho que nunca vi um hífen shebang. Como a palavra é formada por "hash" e "bang", sua ortografia não é muito clara, pois parece que é uma combinação de "ela" e "bang".
Kyle Strand
Você pode chamá-lo hashbang( #= "hash") ou shebang( #= "sharp"), dependendo de como você nomeia o #personagem. No entanto, shebangé realmente mais comum. @KyleStrand
Byte Commander
7

Tecnicamente, não requer isso. Requer um caminho para o ambiente em que seu script é executado. Seus scripts futuros seriam melhores para incluir / usr / bin / env e especificar python. Isso garante que seu script seja executado no ambiente python, não importa onde o python esteja instalado. Você deseja fazer isso por motivos de compatibilidade, não pode ter certeza de que a próxima pessoa com quem você compartilhar seu código terá o python instalado em usr / bin / python ou se eles terão permissões para esses arquivos do sistema.

Aqui está uma sessão de perguntas e respostas semelhante do estouro da pilha .

O que parece no seu script é:

#!/usr/bin/env python

Também vejo alguma preocupação sobre como especificar python3. Aqui está como fazê-lo:

#!/usr/bin/env python3
j0h
fonte
5

No Linux, o Python pode ou não exigir a #!linha (shebang). Isso depende de como os códigos Python são manipulados, executando os códigos no modo interativo Python ou em um script Python.

O modo interativo Python permite ao usuário digitar e executar códigos Python diretamente, o que não requer a linha shebang. Para executar o modo interativo, abra um Terminal e digite pythonPython 2.X ou python3Python 3.X.

$  python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 

$  python3
Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

O script Python permite que o usuário escreva e salve os códigos Python em um arquivo de texto sem formatação e execute os códigos posteriormente. Isso pode ou não exigir a linha shebang. No entanto, existem dois motivos conhecidos quando a linha shebang é necessária para usar o script Python no Linux.

  1. executar códigos Python em um script executável, ou seja, define como os códigos devem ser executados e usando qual interpretador;

  2. executar códigos Python com relação à versão específica do Python, isto é, executar códigos compatíveis apenas com o Python 2.X ou o Python 3.X

Pratique com scripts Python

Abaixo estão a lista e o conteúdo dos arquivos, que usei para mostrar os casos em que a #!linha (shebang) é necessária ou não.

$  ls -ln *.py
-rw-rw-r-- 1 1000 1000  94 Dec 14 18:37 hello1.py
-rwxrwxr-x 1 1000 1000 116 Dec 14 18:37 hello2e.py
-rw-rw-r-- 1 1000 1000 116 Dec 14 18:37 hello2.py
-rwxrwxr-x 1 1000 1000 117 Dec 14 18:37 hello3e.py
-rwxrwxr-x 1 1000 1000 120 Dec 14 18:37 hello3m.py
-rw-rw-r-- 1 1000 1000 117 Dec 14 18:37 hello3.py

$  file *.py
hello1.py:  ASCII text
hello2e.py: Python script, ASCII text executable
hello2.py:  Python script, ASCII text executable
hello3e.py: Python script, ASCII text executable
hello3m.py: Python script, UTF-8 Unicode (with BOM) text executable
hello3.py:  Python script, ASCII text executable
  • hello1.py contém apenas o código fonte.

    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2.py contém código fonte e a linha shebang.

    #!/usr/bin/env python
    import sys
    sys.stdout.write("Hello from Python %s\n" % (sys.version,))
    print("Hello, World!")
  • hello2e.pycontém o mesmo que hello2.pye tornou executável.

  • hello3.pycontém o mesmo que hello2.py, exceto que ele está adaptado para execução no Python 3 renomeando a primeira linha para #!/usr/bin/env python3.

  • hello3e.pycontém o mesmo que hello3.pye tornou executável.

  • hello3m.pycontém o mesmo que hello3.pye é executável, exceto salvo com a Write Unicode BOMopção no editor de texto, ou seja, Mousepad.

Além desse ponto, serão apresentados ao usuário dois métodos para executar os scripts Python. Ambos os métodos foram demonstrados como abaixo.

Método 1: executar com o programa Python

Abaixo estão os comandos e a saída ao executar o código-fonte com Python 2 e Python 3.

$  python hello1.py
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  python3 hello1.py
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Ambas as versões do Python foram capazes de executar o script com sucesso. Portanto, a linha shebang não é necessária ao executar o script Python via pythonou python3comando.

Método 2: executar como script Python

Abaixo estão os comandos e a saída ao executar o código-fonte com a linha shebang, que não são adaptados a Python 2 e Python 3, incluindo casos não executáveis ​​e executáveis.

$  ./hello1.py
bash: ./hello1.py: Permission denied

$  ./hello2.py
bash: ./hello2.py: Permission denied

$  ./hello3.py
bash: ./hello3.py: Permission denied

$  ./hello2e.py 
Hello from Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2]
Hello, World!

$  ./hello3e.py 
Hello from Python 3.4.3 (default, Oct 14 2015, 20:33:09) 
[GCC 4.8.4]
Hello, World!

Os três primeiros scripts falharam porque esses scripts não são executáveis, independentemente de terem ou não a linha shebang (para suporte à prova, consulte Exemplo adicional abaixo). Os dois últimos scripts têm linha shebang e são executáveis.

Aparentemente, um script que foi tornado executável é essencialmente inútil sem a linha shebang. Portanto, a linha shebang é necessária e o script deve ser executável ao executar os códigos Python em um script executável.

Quando shebang não funciona

No meu exemplo preparado e testado, a execução hello3m.pycomo um script executável falhou e retornou um erro.

$  ./hello3m.py 
./hello3m.py: line 1: #!/usr/bin/env: No such file or directory

Essa é uma limitação conhecida de que o shebang não funciona ou se torna inválido. Quando um arquivo é salvo como BOM Unicode (marca de ordem de bytes), ele falha ao executar normalmente como um script Python executável.

Exemplo adicional

Este exemplo adicional deve ser tratado apenas como prova de apoio. O usuário deve evitar executar este exemplo, embora o resultado seja inofensivo.

Eu criei outro arquivo chamado hello1e.py, que contém o mesmo hello1.pye que é executável. A execução desse script retornou um erro de sintaxe.

$  ./hello1e.py 
./hello1e.py: line 2: syntax error near unexpected token `"Hello from Python %s\n"'
./hello1e.py: line 2: `sys.stdout.write("Hello from Python %s\n" % (sys.version,))'

Ao executar esse script, primeiro, o cursor do mouse será alterado para um sinal de mais e não fará nada na aparência. O erro de sintaxe não será mostrado até eu clicar na janela da área de trabalho ou do terminal. Em seguida, esse script criará um sysarquivo no mesmo diretório que o script.

$  file sys
sys: PostScript document text conforming DSC level 3.0, Level 1

O sysarquivo foi identificado como arquivo PostScript, sem extensão de arquivo. Este arquivo pode ser aberto no visualizador de documentos, ou seja, Evince, e o arquivo realmente continha uma captura de tela da janela em que eu havia clicado anteriormente. Na minha experiência, o arquivo pode ser tão grande quanto alguns megabytes.

Mais uma vez, a linha shebang é necessária e o script deve ser executável ao executar o script Python como um script executável. Caso contrário, o script se comportará mal conforme descrito acima.

Notas Adicionais

O termo "tornado executável" ou "deve ser executável" refere-se à permissão para executar o script. Isso é feito executando o chmod +x FILENAMEcomando no Terminal ou marcando a opção "Permitir que este arquivo seja executado como um programa" ou algo semelhante na janela Propriedades , em um gerenciador de arquivos.

Enquanto outras respostas existentes cobriram quase tudo, essa resposta adotou uma abordagem diferente, usando exemplos práticos para explicar o assunto. A sintaxe do código foi escrita com cuidado, de modo que os exemplos possam ser executados com o Python 2 ou Python 3, como ele é.

Os códigos Python foram adaptados de Using Python no Windows e Using Python nas plataformas Unix , com código de uma linha adicional do onipresente "Olá, Mundo!" programa.

Todos os códigos e comandos foram totalmente testados e funcionam no sistema Xubuntu 14.04, que tinha o Python 2.7 e o Python 3.4 instalados por padrão.

clearkimura
fonte
4

Isso significa que, quando esse arquivo é executado, seu computador sabe executá-lo com o programa /usr/bin/python, é assim que você o diferencia de outro idioma, como o bash onde você faria #!/bin/bash. Isso é para que você possa simplesmente executar:

./[file-to-execute]

E ele saberá com qual arquivo executá-lo, em vez de precisar especificar algo como:

python ./[file-to-execute].py

A #!parte é arbitrado geralmente como uma casa de jogo ou de um golpe trituração .

muru
fonte
2
Também um hashbang.
Naftuli Kay
1

Se você tiver várias versões do Python instaladas, /usr/bin/envgarantirá que o intérprete usado seja o primeiro do seu ambiente $PATH. A alternativa seria codificar algo como #!/usr/bin/python;

No Unix, um arquivo executável que deve ser interpretado pode indicar qual intérprete usar com um #!no início da primeira linha, seguido pelo intérprete (e quaisquer sinalizadores que ele possa precisar).

Esta regra é aplicável apenas ao sistema baseado em UNIX.

orvi
fonte
0

útil para sistemas operacionais como o Linux, onde o Python 2.x ainda é o padrão, mas a maioria das pessoas também baixa o 3.x.

2.x seria executado por padrão. Portanto, meu código 3.x, prefixo com #! / Usr / bin / env python3 para que o 3.x execute o código. Posso até especificar a revisão menor (python 3.xyz) se optar por ter versões beta ou apenas versões ligeiramente mais antigas.

user21784
fonte