새로운 언어 기능을 사용하는 프로그램에서 Python 버전을 확인하려면 어떻게해야합니까?


239

적어도 특정 버전의 Python이 필요한 Python 스크립트가있는 경우 이전 버전의 Python을 사용하여 스크립트를 시작할 때 정상적으로 실패하는 올바른 방법은 무엇입니까?

오류 메시지를 발행하고 종료 할 수있을 정도로 일찍 제어하려면 어떻게해야합니까?

예를 들어, ternery 연산자 (2.5의 새로운 기능)와 "with"블록 (2.6의 새로운 기능)을 사용하는 프로그램이 있습니다. 스크립트가 가장 먼저 호출하는 간단한 인터프리터 버전 검사기 루틴을 작성했습니다. 대신, 내 루틴이 호출되기 전에 파이썬 컴파일 중에 스크립트가 실패합니다. 따라서 스크립트 사용자는 매우 모호한시 낙스 오류 역 추적을 볼 수 있습니다. 이는 잘못된 버전의 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

(동료를위한 채널링)


3
"파이썬 버전을 확인하십시오. 문제는 구 버전의 파이썬에서 일부 구문이 잘못되었다는 것입니다." 나는 이것이 어떻게 문제인지 알지 못한다. 버전을 확인할 수 있으면 구문 오류를 피할 수 있습니다. 버전 검사는 구문에 어떻게 적용되지 않습니까? 질문을 명확히 할 수 있습니까?
S.Lott

4
@ S.Lott 아니, 당신은 잘못되지 않습니다, 단지 코드가 읽히지 않고 (구문 분석되지 않고) 실행 되지 않는 어딘가에 코드를 포함시키는 데 어려움이 있다는 것입니다 -이것은 답변이 보여주는 것처럼 즉시 명백하지 않습니다.
Brendan

7
S.Lott, 이전 버전의 Python에서는 컴파일되지 않기 때문에 테스트를 실행할 수 없습니다. 대신 일반적인 구문 오류가 발생합니다. 2.4 인터프리터로 예제 코드를 사용하면 버전 테스트를 수행 할 수 없다는 것을 알 수 있습니다.
Mark Harrison

7
@ S.Lott 글쎄 그것은 당신이 사소한 것으로 간주하는 것에 달려 있습니다. 개인적으로 다른 버전의 Python에 대해 별도의 파일을 만들거나 사소한 추가 프로세스를 생성하는 것을 고려하지 않을 것입니다. 나는이 질문이 가치 있다고 말할 것이다. 특히 파이썬이 단정하고 종종 놀라운 속임수로 가득 차 있다고 생각할 때-나는 구글이 여기에 깔끔한 답변이 있는지 알고 싶어했다
Brendan

7
우리는이 토론의 끝에 도달했다고 생각합니다. 어떻게해야할지 모르는 것에 대해 질문을했고 어떻게해야하는지에 대한 답을 얻었습니다. 나는 아무것도 제안하지 않고 단지 나를 위해 잘 작동하는 orip의 대답을 받아 들였다 (실제로 내가 채널링하는 동료). 비바 르 스택 오버플로!
마크 해리슨

답변:


111

다음을 사용하여 테스트 할 수 있습니다 eval.

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

또한, with 파이썬 2.5에서, 단지 추가 가능합니다 from __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 *

10
이것은 환상적인 답변입니다. 해결해야 할 문제의 주된 문제는 프로그램이 해당 버전의 파이썬에 대해 구문 적으로 정확해야 실행이 시작되기 때문에 새로운 구문을 사용하면 프로그램이 이전 버전의 인터프리터에서 시작할 수 없다는 것입니다. eval은 그 문제를 해결합니다
Autoplectic

7
setuptools로 패키지를 설치하는 경우 소스 파일의 바이트 컴파일이 실패합니다. 또한 런타임 오류 메시지를 생성하는 모든 왜곡은 의미가없는 것처럼 보입니다. 요구 사항을 문서화하여 그대로 두는 것이 어떻습니까?
John Machin

2
간단한 명령문이 아닌 표현식을 확인하려는 경우 exec대신 을 사용해야 합니다 eval. py2k와 py3k 모두에서 stderr에 인쇄 할 함수를 작성하려고 할 때이 문제가 발생했습니다.
Xiong Chiamiov

2
이 솔루션의 더 깨끗한 버전은 "체크"를 별도의 모듈에 넣고 가져 오는 것입니다 ( import스테이션을 시도 / 제외로 래핑 ). SyntaxError내장 함수 또는 표준 라이브러리에 추가 된 것 이외의 다른 사항도 확인해야 할 수도 있습니다 .
Steven

103

다음을 수행하는 프로그램 주위에 랩퍼를 두십시오.

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()는 2.0 이전 파이썬 인터프리터를 사용하는 만남의 사람들에게하려는 경우,하지만 당신은 할 수있는 몇 가지 정규식이 있습니다.

그리고 이것을하는 더 우아한 방법이있을 수 있습니다.


7
참고로 "cur_version> = req_version"은 조건부로 작동해야합니다.
orip

4
sys.version_info기능이 아닙니다.
nh2

3
성공적인 조건부 안에 코드를 넣는 것은 불필요한 들여 쓰기 및 논리 추가이므로 매우 나쁜 습관입니다. 다음과 같이하십시오 : if sys.version_info [: 2] <req_version : print "old"; sys.exit ()-그렇지 않으면 평소처럼 계속합니다.
timss

1
Tim Peters는 "The Zen of Python"에서 "평평한 것이 중첩 된 것보다 낫다"고 말합니다. (Python에서 "import this"를 입력하면이 내용을 볼 수 있습니다)
Christopher Shroba

1
@ChristopherShroba 감사합니다 import this. 사랑스러운 기분 전환.
Samuel Harmer

32

시험

수입 플랫폼
platform.python_version ()

"2.3.1"과 같은 문자열을 제공해야합니다. 이것이 정확히 맞지 않으면 "플랫폼"내장을 통해 사용 가능한 풍부한 데이터 세트가 있습니다. 당신이 원하는 것은 어딘가에 있어야합니다.


4
-1 : 업데이트 된 질문에 설명 된대로 작동하지 않습니다. 최신 버전의 Python에서 구문을 사용하면 파일이 컴파일되지 않으며 컴파일되지 않으면 파일을 실행하고 버전을 확인할 수 없습니다!
Scott Griffiths

1
@ScottGriffiths print(platform.python_version())대신 실행 platform.python_version()!
Suriyaa

@ScottGriffiths 또한 내 답변을 확인하십시오 : stackoverflow.com/a/40633458/5157221 .
Suriyaa

22

이 버전 비교를 수행하는 가장 좋은 방법은을 사용하는 것 sys.hexversion입니다. 버전 튜플을 비교하면 모든 파이썬 버전에서 원하는 결과를 얻지 못하기 때문에 중요합니다.

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"

나는 이것이 가장 우아하다고 생각하지만 다른 개발자가 이해하기 가장 쉬운 것은 아닙니다.
Nick Bolton

5
어떤 상황에서 버전 튜플을 비교해도 원하는 결과를 얻지 못할 수 있습니까?
SpoonMeiser

버전 튜플에는 영숫자 값도 포함될 수 있습니다.
sorin

8
-1 : 업데이트 된 질문에 설명 된대로 작동하지 않습니다. 최신 버전의 Python에서 구문을 사용하면 파일이 컴파일되지 않으며 컴파일되지 않으면 파일을 실행하고 버전을 확인할 수 없습니다!
Scott Griffiths

어떤 버전 / 플랫폼에서 실패합니까?
sorin

15
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")

7
Python 2.6 이하에서는 명명 된 튜플 sys.version_info아닙니다 . sys.version_info[0]메이저 버전 번호와 sys.version_info[1]마이너 버전 번호 를 사용해야 합니다 .
coredumperror

9

AskUbuntu의 Nykakin 답변 :

platform표준 라이브러리의 모듈을 사용하여 코드 자체에서 Python 버전을 확인할 수도 있습니다.

두 가지 기능이 있습니다.

  • platform.python_version() (문자열을 반환).
  • platform.python_version_tuple() (튜플을 반환).

파이썬 코드

예를 들어 파일을 작성하십시오. 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')

Windows 10에서 WAMP Server를 통해 CGI를 사용한 Python 출력 :

Suriyaa Kudo의 스크린 샷 2016-11-16 14.39.01


유용한 자료


7

이전 버전과의 호환성을 유지하기 위해 Python 2.4에서 집합은 핵심 언어의 일부가되었습니다. 나는 그때 그 일을했는데, 그것은 당신에게도 효과가 있습니다.

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

3
버전 대신 기능을 확인하는 것이 좋습니다. try: set except NameError: from sets import Set as set
orip

@orip : 왜요? 기능이 어떤 버전으로 도입되었는지 알고 있다면 여기에서 설명하는 것처럼 위의 코드를 사용하십시오. 아무 문제가 없습니다.
André

7

문제는 있지만 오류 메시지를 발행 하고 종료 하기에 충분히 일찍 제어하려면 어떻게해야 합니까?

내가 대답하는 질문은 : 앱을 시작하기 전에 오류 메시지를 발행하기에 충분히 일찍 제어하려면 어떻게해야 합니까?

다른 게시물과는 많이 다르게 대답 할 수 있습니다. 지금까지 답변이 Python 내에서 귀하의 질문을 해결하려고하는 것 같습니다.

파이썬을 시작하기 전에 버전을 확인하십시오. 나는 당신의 경로가 리눅스 또는 유닉스임을 봅니다. 그러나 Windows 스크립트 만 제공 할 수 있습니다. 리눅스 스크립팅 구문에 적응시키는 이미지는 그리 어렵지 않습니다.

버전 2.7의 DOS 스크립트는 다음과 같습니다.

@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 예외가 발생하지 않습니다. 임시 파일을 작성하거나 OS 환경 변수를 추가하지 않습니다. 버전 구문 규칙이 다르기 때문에 앱을 예외로 끝내지 않습니다. 보안 액세스 지점이 3 개 줄었습니다.

FOR /F라인의 핵심입니다.

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

여러 파이썬 버전 확인 URL을 확인하십시오 : http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17

그리고 내 핵 버전 :

[MS 스크립트; Python 모듈의 Python 버전 확인 사전 출시] http://pastebin.com/aAuJ91FQ


그 다운 투표를 위해 이유를 설명하는 것을 두려워하지 마십시오.
DevPlayer

정확히 내가 찾고 있었다. 감사! %% H는 무엇입니까?
Clocker

@Clocker python.exe -V는 "Python 2.7"문자열을 반환합니다. 콘솔은 "Python"문자열을 %% G에, 자동 생성 된 os var %% H (G 다음 문자)에 "2.7"문자열을 넣습니다. 에코 %% H | find "2.7"DOS 명령으로 "2.7"파이프를 찾으십시오 "2.7"에서 %% H가 발견되면 오류 레벨을 1로 설정하는 "2.7"을 찾으십시오. DOS 찾기 명령을 사용하여 1이 발생하는 오류 수준을 통해 DOS 배치 레이블로 분기 할 수 있습니다. : Python27
DevPlayer

3
import sys
sys.version

이 같은 대답을 얻을 것이다

'2.7.6 (기본값, 2016 년 10 월 26 일, 20:30:19) \ n [GCC 4.8.4]'

여기 2.7.6 은 버전입니다


2

위에서 언급 한 것처럼 구문 오류는 런타임이 아니라 컴파일 타임에 발생합니다. 파이썬은 "통역 된 언어"이지만, 파이썬 코드는 실제로 직접 해석되지는 않습니다. 바이트 코드로 컴파일 된 다음 해석됩니다. 컴파일 단계는 모듈을 가져올 때 (.pyc 또는 .pyd 파일 형식으로 사용 가능한 이미 컴파일 된 버전이없는 경우) 발생하며 오류가 발생했을 때 발생합니다 (정확하지 않음). 코드가 실행 중입니다.

컴파일 단계를 끝내고 위에서 언급 한대로 eval을 사용하여 원하는 경우 한 줄의 코드에 대해 런타임에 수행 할 수는 있지만 개인적으로 파이썬이 잠재적으로 수행하기 때문에 그렇게하지 않는 것이 좋습니다. 불필요한 런타임 컴파일, 한 가지, 다른 것의 경우 코드 혼란처럼 느껴집니다. (원하는 경우 코드를 생성하는 코드를 생성하는 코드를 생성 할 수 있으며 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)와 같은 한 줄의 구문으로 함수를 작성할 수도 있습니다.)

지적 할 가치가있는 또 다른 것은 (아직 아무도 지적하지 않은 것에 약간 놀랐습니다) 파이썬의 이전 버전은 다음과 같은 코드를 지원하지 않았다는 것입니다

value = 'yes' if MyVarIsTrue else 'no'

..it 같은 코드를 지원했습니다

value = MyVarIsTrue and 'yes' or 'no'

그것은 삼항 표현을 쓰는 오래된 방법이었습니다. 필자는 아직 Python 3을 설치하지 않았지만 지금까지 알고있는 한 "오래된"방식이 여전히 작동하기 때문에 필요한 경우 새로운 구문을 조건부로 사용할 가치가 있는지 스스로 결정할 수 있습니다. 이전 버전의 Python 사용을 지원합니다.


2
진심이야? 사소한 구조를 변경할 수 있도록 코드를 복제 하시겠습니까? 왝. 아주 ck 그리고 a and b or c대신에 b if a else c, 그것은 동등하지 않습니다; 경우 bfalsy입니다 그것은 생산, 실패 a보다는 b.
크리스 모건

1
중복 코드를 제안하지 않고 버전마다 다른 서명이없는 버전 별 코드에 대한 래퍼 함수를 ​​만들고 해당 기능을 버전 별 모듈에 넣는 것이 좋습니다. 1 ~ 5 줄 길이의 함수에 대해 이야기하고 있습니다. b가 false로 평가 될 수있는 경우에 a가 c이면 a와 b 또는 c가 b와 동일하지 않다는 것은 사실입니다. 그래서 나는 common_ops_2_4.py의 ifAThenBElseC (a, b, c)가 1 대신 2 또는 3 줄이어야한다고 생각합니다.이 방법은 실제로 일반적인 관용구를 함수로 캡슐화하여 모든 코드를 줄입니다.
Shavais

2

파일 맨 위에 다음을 넣으십시오.

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...

1
오히려 사용sys.version_info < (2, 7)
Antti Haapala

@AnttiHaapala 이것은 나에게 완벽합니다. 왜 sys.version_info유형을 튜플 과 비교할 수 있는지 설명 할 수 있습니까?
jjj

@jjj sys.version_info 예전 튜플; 예를 들어 (2, 4, 6, 'final', 0); 파이썬 3과 2.7에서만 튜플과 비교할 수있는 별도의 유형으로 변경되었습니다.
Antti Haapala

@AnttiHaapala 나는 그 접근법이 내 것보다 낫다 ... 고마워!
jml

1

가장 좋은 방법은 버전이 아닌 기능을 테스트하는 것입니다. 어떤 경우에는 사소한 것이지 다른 경우에는 그렇지 않습니다.

예 :

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

try / except 블록을 충분히 사용하는 한 대부분의베이스를 커버 할 수 있습니다.


2
네가 옳아. 그것이 그가 요청한 방법입니다-때로는 버전 Y의 기능 테스트는 버전 X의 바이트 코드로 컴파일조차하지 않으므로 직접 수행 할 수 없습니다.
orip

1

방금 빠른 검색 후이 질문을 직접 발견하면서 문제를 직접 해결하려고 시도했으며 위의 제안 중 일부를 기반으로 하이브리드를 만들었습니다.

나는 래퍼 스크립트를 사용하는 DevPlayer의 아이디어를 좋아하지만 단점은 다른 OS에 대해 여러 래퍼를 유지 관리한다는 것이므로 파이썬으로 래퍼를 작성하기로 결정했지만 동일한 기본 "exe를 실행하여 버전을 가져 오기"논리를 사용하기로 결정했습니다. 그리고 이것을 생각해 냈습니다.

2.5 이상에서 작동해야한다고 생각합니다. 나는 지금까지 Linux에서 2.66, 2.7.0 및 3.1.2에서 그리고 OS X에서 2.6.1에서 테스트했습니다.

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") )

예, 최종 디코딩 / 스트립 라인이 끔찍하다는 것을 알고 있지만 버전 번호를 빨리 잡고 싶었습니다. 나는 그것을 다듬을 것입니다.

이것은 현재로서는 나에게 잘 작동하지만, 누군가가 그것을 향상시킬 수 있다면 (또는 그것이 끔찍한 아이디어인지 말해 줄 수 있다면) 너무 멋질 것입니다.


1

대한 독립 파이썬 스크립트, 다음 모듈의 문서화 문자열의 트릭은 파이썬 버전 (여기 v2.7.x) (* nix에서 스크립트 테스트) 작품을 적용합니다.

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

import sys
[...]

이것은 누락 된 파이썬 실행 파일도 처리해야하지만 grep에 종속됩니다. 배경 은 여기 를 참조 하십시오 .


0

sys.hexversion또는로 확인할 수 있습니다 sys.version_info.

sys.hexversion16 진수이므로 인간 친화적이지 않습니다. 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비록 인간 친화적이지 않지만 합니다.

이것이 도움이 되었기를 바랍니다.


0

akhan의 훌륭한 답변을 확장 하여 Python 스크립트가 컴파일 되기 전에 유용한 메시지를 인쇄합니다 .

스크립트가 Python 3.6 이상에서 실행되도록하려면 다음 두 줄을 Python 스크립트 맨 위에 추가하십시오.

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

(참고 : 두 번째 줄은 4 개의 작은 따옴표로 시작하고 3 개의 작은 따옴표로 끝납니다 . 이상하게 보일 수 있지만 오타가 아닙니다.)

이 솔루션의 장점은 3.6 이전의 Python 버전을 사용 print(f'Hello, {name}!')하는 SyntaxError경우 와 같은 코드로 인해 발생하지 않는다는 것입니다. 대신이 유용한 메시지가 나타납니다.

This script requires Python 3.6 or newer.

물론이 솔루션은 유닉스 계열 쉘에서만 작동하며 스크립트가 직접 호출 된 경우 (예 ./script.py:), 적절한 eXecute 권한 비트가 설정되어 있어야합니다.


-2

이건 어때요:

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

5
-1 : 업데이트 된 질문에 설명 된대로 작동하지 않습니다. 최신 버전의 Python에서 구문을 사용하면 파일이 컴파일되지 않으며 컴파일되지 않으면 파일을 실행하고 버전을 확인할 수 없습니다!
Scott Griffiths

-3

문제는 매우 간단합니다. 버전이 있다면 당신은 확인 미만 , 2.4 이상이어야 거나 같음 . 따라서 파이썬 버전이 2.4이면 2.4 이상입니다. 당신이 가졌어야 할 것은 :

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

아니

    if sys.version_info < (2, 4):

4
단락 3과 업데이트를 읽으십시오. 새 언어 구문을 사용하는 경우 코드가 2.4에서 컴파일되지 않기 때문에이 코드를 실행할 시점이 아닙니다.
마크 해리슨

보다 작았지만 평가가 누락되었습니다.
Craig
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.