Se eu tenho um script Python que requer pelo menos uma versão específica do Python, qual é a maneira correta de falhar normalmente quando uma versão anterior do Python é usada para iniciar o script?
Como obtenho controle cedo o suficiente para emitir uma mensagem de erro e sair?
Por exemplo, eu tenho um programa que usa o operador ternery (novo no 2.5) e blocos "com" (novo no 2.6). Eu escrevi uma rotina simples de verificação de versão para intérpretes, que é a primeira coisa que o script chamaria ... exceto que não chega tão longe. Em vez disso, o script falha durante a compilação do python, antes mesmo de minhas rotinas serem chamadas. Assim, o usuário do script vê alguns rastreamentos de erros de sinaxia muito obscuros - o que exige que um especialista deduza que é simplesmente o caso de executar a versão errada do Python.
Eu sei como verificar a versão do Python. O problema é que algumas sintaxes são ilegais nas versões mais antigas do Python. Considere este programa:
import sys
if sys.version_info < (2, 4):
raise "must use python 2.5 or greater"
else:
# syntax error in 2.4, ok in 2.5
x = 1 if True else 2
print x
Quando executado sob 2.4, quero esse resultado
$ ~/bin/python2.4 tern.py
must use python 2.5 or greater
e não este resultado:
$ ~/bin/python2.4 tern.py
File "tern.py", line 5
x = 1 if True else 2
^
SyntaxError: invalid syntax
(Canalizando para um colega de trabalho.)
Respostas:
Você pode testar usando
eval
:Além disso,
with
está disponível no Python 2.5, basta adicionarfrom __future__ import with_statement
.EDIT: para obter o controle cedo o suficiente, você pode dividi-lo em
.py
arquivos diferentes e verificar a compatibilidade no arquivo principal antes de importar (por exemplo,__init__.py
em um pacote):fonte
exec
vez deeval
. Eu tive esse problema ao tentar escrever uma função que seria impressa em stderr em py2k e py3k.import
estação em try / except). Observe que você pode precisar verificar outras coisas alémSyntaxError
disso (por exemplo, funções internas ou adições à biblioteca padrão)Tenha um wrapper ao redor do seu programa que faça o seguinte.
Você também pode considerar o uso
sys.version()
, se planeja encontrar pessoas que estão usando intérpretes Python anteriores à 2.0, mas ainda tem algumas expressões regulares a fazer.E pode haver maneiras mais elegantes de fazer isso.
fonte
sys.version_info
não é uma função.import this
. Uma diversão adorável.Experimentar
Deve fornecer uma string como "2.3.1". Se isso não for exatamente o que você deseja, existe um rico conjunto de dados disponíveis por meio do build-in "plataforma". O que você quer deve estar lá em algum lugar.
fonte
print(platform.python_version())
vez deplatform.python_version()
!Provavelmente, a melhor maneira de fazer essa comparação de versão é usar o
sys.hexversion
. Isso é importante porque comparar as tuplas de versão não fornecerá o resultado desejado em todas as versões do python.fonte
fonte
sys.version_info
é uma tupla nomeada. Você precisará usar o número da versão principal e o menor.sys.version_info[0]
sys.version_info[1]
Você também pode verificar a versão do Python a partir do próprio código usando
platform
módulo da biblioteca padrão.Existem duas funções:
platform.python_version()
(retorna string).platform.python_version_tuple()
(retorna tupla).O código Python
Método fácil de verificar a versão:
Você também pode usar o
eval
método:Execute o arquivo Python em uma linha de comando:
A saída do Python com CGI por meio de um servidor WAMP no Windows 10:
Recursos úteis
fonte
Os conjuntos se tornaram parte da linguagem principal do Python 2.4, a fim de permanecer compatível com versões anteriores. Eu fiz isso naquela época, o que também funcionará para você:
fonte
try: set except NameError: from sets import Set as set
Embora a pergunta seja: como obtenho controle cedo o suficiente para emitir uma mensagem de erro e sair ?
A pergunta que respondo é: Como obtenho controle cedo o suficiente para emitir uma mensagem de erro antes de iniciar o aplicativo ?
Posso responder de maneira muito diferente das outras postagens. Parece que as respostas até agora estão tentando resolver sua pergunta no Python.
Eu digo, faça a verificação da versão antes de lançar o Python. Vejo que seu caminho é Linux ou unix. No entanto, só posso oferecer um script do Windows. Eu imagem adaptá-lo à sintaxe de script linux não seria muito difícil.
Aqui está o script do DOS com a versão 2.7:
Isso não executa nenhuma parte do seu aplicativo e, portanto, não gera uma exceção do Python. Ele não cria nenhum arquivo temporário ou adiciona variáveis de ambiente do SO. E isso não encerra seu aplicativo a uma exceção devido a diferentes regras de sintaxe da versão. São três pontos de acesso de segurança menos possíveis.
A
FOR /F
linha é a chave.Para várias versões de python, confira o URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17
E minha versão hack:
[Script MS; Pré-lançamento da verificação da versão do Python do módulo Python] http://pastebin.com/aAuJ91FQ
fonte
estará recebendo resposta como esta
aqui 2.7.6 é a versão
fonte
Como observado acima, erros de sintaxe ocorrem no tempo de compilação, não no tempo de execução. Enquanto Python é uma "linguagem interpretada", o código Python não é realmente diretamente interpretado; é compilado para código de bytes, que é então interpretado. Há uma etapa de compilação que acontece quando um módulo é importado (se ainda não existe uma versão compilada disponível na forma de um arquivo .pyc ou .pyd) e é nesse momento que você recebe o erro, não (exatamente) quando seu código está sendo executado.
Você pode adiar a etapa de compilação e fazê-la acontecer em tempo de execução para uma única linha de código, se você quiser, usando eval, conforme observado acima, mas eu pessoalmente prefiro evitar fazer isso, porque faz com que o Python execute potencialmente compilação desnecessária em tempo de execução, por um lado, e por outro, cria o que para mim parece desordem de código. (Se você quiser, pode gerar código que gera código que gera código - e ter um tempo absolutamente fabuloso modificando e depurando isso dentro de seis meses.) Portanto, o que eu recomendaria é algo mais ou menos assim:
.. o que eu faria mesmo se tivesse apenas uma função que usasse sintaxe mais recente e que fosse muito curta. (De fato, eu tomaria todas as medidas razoáveis para minimizar o número e o tamanho de tais funções. Eu poderia até escrever uma função como ifTrueAElseB (cond, a, b) com essa única linha de sintaxe.)
Outra coisa que vale a pena ressaltar (que estou um pouco surpreso que ninguém apontou ainda) é que, enquanto as versões anteriores do Python não suportavam códigos como
..ele suportava código como
Essa era a maneira antiga de escrever expressões ternárias. Ainda não tenho o Python 3 instalado, mas até onde eu sei, essa maneira "antiga" ainda funciona até hoje, para que você possa decidir por si próprio se vale a pena usar condicionalmente a nova sintaxe, se necessário para suportar o uso de versões mais antigas do Python.
fonte
a and b or c
invés deb if a else c
, não é equivalente; seb
for falso, falhará, produzindoa
e nãob
.Coloque o seguinte na parte superior do seu arquivo:
Continue com o código Python normal:
fonte
sys.version_info < (2, 7)
sys.version_info
tipo com uma tupla funciona?sys.version_info
costumava ser uma tupla; por exemplo(2, 4, 6, 'final', 0)
; somente no Python 3 e 2.7 foi alterado para um tipo separado, que é, no entanto, comparável às tuplas.Eu acho que a melhor maneira é testar a funcionalidade em vez de versões. Em alguns casos, isso é trivial, não em outros.
por exemplo:
Contanto que você seja suficientemente específico ao usar os blocos try / except, poderá cobrir a maior parte de suas bases.
fonte
Acabei de encontrar essa pergunta depois de uma pesquisa rápida enquanto tentava resolver o problema sozinho e criei um híbrido com base em algumas das sugestões acima.
Eu gosto da ideia do DevPlayer de usar um script de wrapper, mas a desvantagem é que você acaba mantendo vários wrappers para sistemas operacionais diferentes, então decidi escrever o wrapper em python, mas use a mesma lógica básica "pegue a versão executando o exe" e veio com isso.
Eu acho que deve funcionar para 2,5 em diante. Eu testei no 2.66, 2.7.0 e 3.1.2 no Linux e 2.6.1 no OS X até agora.
Sim, eu sei que a linha final de decodificação / tira é horrível, mas eu só queria pegar rapidamente o número da versão. Eu vou refinar isso.
Isso funciona bem o suficiente para mim por enquanto, mas se alguém puder melhorá-lo (ou me diga por que é uma péssima ideia), isso também seria legal.
fonte
Para scripts python independentes , o seguinte truque de documentação do módulo para impor uma versão python (aqui v2.7.x) funciona (testado em * nix).
Isso também deve lidar com o executável python ausente, mas depende do grep. Veja aqui o plano de fundo.
fonte
Você pode verificar com
sys.hexversion
ousys.version_info
.sys.hexversion
não é muito amigável ao ser humano porque é um número hexadecimal.sys.version_info
é uma tupla, por isso é mais amigável ao ser humano.Verifique o Python 3.6 ou mais recente com
sys.hexversion
:Verifique o Python 3.6 ou mais recente com
sys.version_info
:sys.version_info
é mais amigável ao ser humano, mas leva mais personagens. Eu recomendariasys.hexversion
, mesmo que seja menos amigável ao ser humano.Espero que isso tenha ajudado!
fonte
Estou expandindo a excelente resposta do akhan, que imprime uma mensagem útil antes que o script Python seja compilado.
Se você deseja garantir que o script esteja sendo executado com o Python 3.6 ou mais recente, adicione estas duas linhas na parte superior do seu script Python:
(Observação: a segunda linha começa com quatro aspas simples e termina com três aspas simples. Isso pode parecer estranho, mas não é um erro de digitação.)
A vantagem desta solução é que código como
print(f'Hello, {name}!')
não causará umSyntaxError
se uma versão Python anterior a 3.6 for usada. Você verá esta mensagem útil:Obviamente, essa solução funciona apenas em shells semelhantes ao Unix, e somente quando o script é chamado diretamente (como
./script.py
:) e com os bits de permissão eXecute adequados definidos.fonte
Que tal agora:
fonte
O problema é bastante simples. Você verificou se a versão era menor que 2.4, não menor ou igual a . Portanto, se a versão Python for 2.4, não será menor que 2.4. O que você deveria ter tido era:
, não
fonte