Как я могу проверить версию Python в программе, которая использует новые возможности языка?

StackOverflow https://stackoverflow.com/questions/446052

  •  22-07-2019
  •  | 
  •  

Вопрос

Если у меня есть скрипт Python, который требует хотя бы определенного версия Python, какой правильный способ потерпеть неудачу грациозно когда для запуска скрипта используется более ранняя версия Python?

Как получить контроль достаточно рано, чтобы выдать сообщение об ошибке и выход?

Например, у меня есть программа, которая использует оператор ternery (новый в 2.5) и "с" блоками (новый пункт 2.6).Я написал простую маленькую интерпретатор-версию проверка рутины, которая является первым, что сценарий будет Meme it звонить ...за исключением того, что это не заходит так далеко.Вместо этого, скрипт терпит неудачу во время компиляции python, перед моими процедурами даже называют.Таким образом, пользователь скрипта видит некоторые очень непонятные трассировки ошибок синакса - которые в значительной степени требуют эксперт, чтобы сделать вывод, что это просто случай бега Meme it неправильная версия Python.

Я знаю, как проверить версию Python.Проблема в том, что некоторый синтаксис недопустим в старых версиях Python.Рассмотрим эту программу:

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

При запуске под 2.4 я хочу этот результат

$ ~/bin/python2.4 tern.py 
must use python 2.5 or greater

а не этот результат:

$ ~/bin/python2.4 tern.py 
  File "tern.py", line 5
    x = 1 if True else 2
           ^
SyntaxError: invalid syntax

(Ченнелинг для коллеги.)

Это было полезно?

Решение

Вы можете проверить, используя eval :

try:
  eval("1 if True else 2")
except SyntaxError:
  # doesn't have ternary

Кроме того, с доступен в Python 2.5, просто добавьте из __future__ import with_statement .

РЕДАКТИРОВАТЬ: чтобы получить контроль достаточно рано, вы можете разбить его на разные файлы .py и проверить совместимость в главном файле перед импортом (например, в __ init __. py в пакет):

# __init__.py

# Check compatibility
try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

# import from another module
from impl import *

Другие советы

Оберните вокруг своей программы оболочку, которая выполняет следующие действия.

import sys

req_version = (2,5)
cur_version = sys.version_info

if cur_version >= req_version:
   import myApp
   myApp.run()
else:
   print "Your Python interpreter is too old. Please consider upgrading."

Вы также можете рассмотреть возможность использования sys.version () , если вы планируете встречать людей, которые используют интерпретаторы Python до 2.0, но у вас есть несколько регулярных выражений.

И для этого могут быть более элегантные способы.

Попробуйте

import platform
platform.python_version()

Должен дать вам строку типа "2.3.1". Если это не совсем то, что вам нужно, есть богатый набор данных, доступных через " платформу " встроенные. То, что вы хотите, должно быть где-то там.

Вероятно, лучший способ сделать это сравнение версий - это использовать sys.hexversion . Это важно, потому что сравнение кортежей версий не даст желаемого результата во всех версиях Python.

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"
import sys    
# prints whether python is version 3 or not
python_version = sys.version_info.major
if python_version == 3:
    print("is python 3")
else:
    print("not python 3")

Ответ от Ныкакин на СпроситеUbuntu:

Вы также можете проверить версию Python из самого кода, используя platform модуль из стандартной библиотеки.

Есть две функции:

  • platform.python_version() (возвращает строку).
  • platform.python_version_tuple() (возвращает кортеж).

Код Python

Создайте файл, например: version.py)

Простой способ проверить версию:

import platform

print(platform.python_version())
print(platform.python_version_tuple())

Вы также можете использовать eval метод:

try:
  eval("1 if True else 2")
except SyntaxError:
  raise ImportError("requires ternary support")

Запустите файл Python в командной строке:

$ python version.py 
2.7.11
('2', '7', '11')

Вывод Python с CGI через WAMP-сервер в Windows 10:

Screenshot 2016-11-16 14.39.01 by Suriyaa Kudo


Полезные ресурсы

Наборы стали частью основного языка в Python 2.4 для обеспечения обратной совместимости. Я сделал это тогда, что будет работать и для вас:

if sys.version_info < (2, 4):
    from sets import Set as set

Хотя вопрос в том, Как получить контроль достаточно рано, чтобы выдать сообщение об ошибке и выйти ?

Вопрос, на который я отвечаю: Как получить контроль достаточно рано, чтобы выдавать сообщение об ошибке перед запуском приложения ?

Я могу ответить на это по-другому, чем другие посты. Кажется, что ответы до сих пор пытаются решить ваш вопрос изнутри Python.

Я говорю, сделайте проверку версии перед запуском Python. Я вижу, ваш путь - Linux или Unix. Однако я могу предложить вам только сценарий Windows. Я представляю, что адаптировать его к синтаксису сценариев Linux не будет слишком сложно.

Вот сценарий DOS с версией 2.7:

@ECHO OFF
REM see http://ss64.com/nt/for_f.html
FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul
IF NOT ErrorLevel 1 GOTO Python27
ECHO must use python2.7 or greater
GOTO EOF
:Python27
python.exe tern.py
GOTO EOF
:EOF

Это не запускает какую-либо часть вашего приложения и, следовательно, не вызовет исключение Python. Он не создает временный файл и не добавляет никаких переменных среды ОС. И это не заканчивает ваше приложение исключением из-за различных правил синтаксиса версий. Это на три менее возможных точки безопасности доступа.

Строка FOR / F является ключом.

FOR /F "tokens=1,2" %%G IN ('"python.exe -V 2>&1"') DO ECHO %%H | find "2.7" > Nul

Для нескольких версий Python проверьте URL: http://www.fpschultze.de/modules/smartfaq/faq. PHP? faqid = 17

И моя версия взлома:

[MS script; Проверка версии Python перед запуском модуля Python] http://pastebin.com/aAuJ91FQ

import sys
sys.version

будет получать такой ответ

  

'2.7.6 (по умолчанию, 26 октября 2016 г., 20:30:19) \ n [GCC 4.8.4]'

здесь 2.7.6 - версия

Как отмечалось выше, синтаксические ошибки возникают во время компиляции, а не во время выполнения.Хотя Python является «интерпретируемым языком», код Python на самом деле не интерпретируется напрямую;он компилируется в байт-код, который затем интерпретируется.Существует этап компиляции, который происходит при импорте модуля (если нет уже скомпилированной версии в виде файла .pyc или .pyd), и именно тогда вы получаете ошибку, а не (совершенно точно), когда ваш код работает.

Вы можете отложить этап компиляции и сделать его во время выполнения для одной строки кода, если хотите, используя eval, как отмечено выше, но я лично предпочитаю избегать этого, потому что это потенциально приводит к потенциальной производительности Python. ненужная компиляция во время выполнения, с одной стороны, а с другой - создает то, что мне кажется беспорядок в коде.(Если хотите, вы можете сгенерировать код, который генерирует код, который генерирует код, и прекрасно провести время, модифицируя и отлаживая его через 6 месяцев.) Вместо этого я бы порекомендовал что-то вроде этого:

import sys
if sys.hexversion < 0x02060000:
    from my_module_2_5 import thisFunc, thatFunc, theOtherFunc
else:
    from my_module import thisFunc, thatFunc, theOtherFunc

..что я бы сделал, даже если бы у меня была только одна функция с новым синтаксисом, и она была бы очень короткой.(На самом деле я бы принял все разумные меры, чтобы минимизировать количество и размер таких функций.Я мог бы даже написать функцию типа ifTrueAElseB(cond, a, b) с этой единственной строкой синтаксиса.)

Еще одна вещь, на которую, возможно, стоит обратить внимание (я немного удивлен, что никто еще не обратил на это внимания), заключается в том, что, хотя более ранние версии Python не поддерживали такой код, как

value = 'yes' if MyVarIsTrue else 'no'

... он поддерживал такой код, как

value = MyVarIsTrue and 'yes' or 'no'

Это был старый способ написания троичных выражений.У меня пока не установлен Python 3, но, насколько я знаю, этот "старый" способ работает и по сей день, так что вы сами можете решить, стоит ли условно использовать новый синтаксис, если вам нужно для поддержки использования старых версий Python.

Поместите следующее в самый верх вашего файла:

import sys

if float(sys.version.split()[0][:3]) < 2.7:
    print "Python 2.7 or higher required to run this code, " + sys.version.split()[0] + " detected, exiting."
    exit(1)

Затем продолжите с нормальным кодом Python:

import ...
import ...
other code...

Я думаю, что лучший способ — тестировать функциональность, а не версии.В некоторых случаях это тривиально, в других – нет.

например:

try :
    # Do stuff
except : # Features weren't found.
    # Do stuff for older versions.

Если вы достаточно конкретно используете блоки try/Exception, вы можете охватить большую часть своих баз.

Я только что нашел этот вопрос после быстрого поиска, пытаясь решить проблему самостоятельно, и я придумал гибрид, основанный на нескольких из приведенных выше предложений.

Мне нравится идея DevPlayer об использовании скрипта-обертки, но недостатком является то, что вам приходится поддерживать несколько оберток для разных ОС, поэтому я решил написать обертку на python, но использовать одну и ту же базовую версию " захватить версию, запустив exe " логика и придумали это.

Я думаю, что это должно работать в течение 2.5 и далее. Я протестировал его на 2.66, 2.7.0 и 3.1.2 в Linux и 2.6.1 в OS X.

import sys, subprocess
args = [sys.executable,"--version"]

output, error = subprocess.Popen(args ,stdout = subprocess.PIPE, stderr = subprocess.PIPE).communicate()
print("The version is: '%s'"  %error.decode(sys.stdout.encoding).strip("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLMNBVCXZ,.+ \n") )

Да, я знаю, что окончательная строка декодирования / полосы ужасна, но я просто хотела быстро получить номер версии. Я собираюсь уточнить это.

Пока это работает достаточно хорошо для меня, но если кто-нибудь сможет улучшить его (или скажите мне, почему это ужасная идея), это тоже было бы здорово.

Для автономных сценариев Python работает следующий трюк docstring модуля для принудительного применения версии Python (здесь v2.7.x) (проверено на * nix).

#!/bin/sh
''''python -V 2>&1 | grep -q 2.7 && exec python -u -- "<*>" ${1+"$@"}; echo "python 2.7.x missing"; exit 1 # '''

import sys
[...]

Это также должно обрабатывать отсутствующий исполняемый файл Python, но зависит от grep. См. здесь для фона.

Вы можете проверить с помощью sys.hexversion или sys.version_info .

sys.hexversion не очень удобен для человека, потому что это шестнадцатеричное число. sys.version_info - это кортеж, поэтому он более удобен для человека.

Проверьте для Python 3.6 или новее с помощью sys.hexversion :

import sys, time
if sys.hexversion < 0x30600F0:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

Проверьте наличие Python 3.6 или новее с помощью sys.version_info :

import sys, time
if sys.version_info[0] < 3 and sys.version_info[1] < 6:
    print("You need Python 3.6 or greater.")
    for _ in range(1, 5): time.sleep(1)
    exit()

sys.version_info более удобен для человека, но занимает больше символов. Я бы порекомендовал sys.hexversion , даже если он менее дружественный для человека.

Надеюсь, это тебе помогло!

Я расширяю превосходный ответ Ахана, который печатает полезное сообщение до того, как сценарий Python будет даже скомпилирован.

Если вы хотите убедиться, что скрипт выполняется с Python 3.6 или новее, добавьте эти две строки в начало вашего скрипта Python:

#!/bin/sh
''''python3 -c 'import sys; sys.exit(sys.version_info < (3, 6))' && exec python3 -u -- "
This script requires Python 3.6 or newer.
" ${1+"$@"}; echo 'This script requires Python 3.6 or newer.'; exit 1 # '''

(Примечание. Вторая строка начинается с четырех одинарных кавычек и заканчивается тремя одинарными кавычками. Это может показаться странным, но это не опечатка.)

Преимущество этого решения заключается в том, что такой код, как print (f'Hello, {name}! ') не будет вызывать SyntaxError , если версия Python старше 3.6 используется. Вместо этого вы увидите это полезное сообщение:

<*>

Конечно, это решение работает только на Unix-подобных оболочках и только тогда, когда скрипт вызывается напрямую (например, ./ script.py ), и с установленными битами разрешения eXecute. .

Как насчет этого?

import sys

def testPyVer(reqver):
  if float(sys.version[:3]) >= reqver:
    return 1
  else:
    return 0

#blah blah blah, more code

if testPyVer(3.0) == 1:
  #do stuff
else:
  #print python requirement, exit statement

Проблема довольно проста. Вы проверили, была ли версия меньше 2,4, не меньше или равна . Так что, если версия Python 2.4, она не меньше 2.4. То, что вы должны были, было:

    if sys.version_info **<=** (2, 4):

, а не

    if sys.version_info < (2, 4):
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top