Jak mogę sprawdzić wersję Pythona w programie, który używa nowych funkcji językowych?

Jeśli mam skrypt Pythona, który wymaga co najmniej określonego wersja Pythona, jaki jest prawidłowy sposób na porażkę kiedy do uruchomienia skryptu używana jest wcześniejsza wersja Pythona?

Jak uzyskać kontrolę wystarczająco wcześnie, aby wydać komunikat o błędzie i wyjście?

Na przykład, mam program, który używa operatora ternery (nowy w 2.5) i "z" blokami (nowość w 2.6). Napisałem prosty mały interpreter-wersja Checker rutyna, która jest pierwszą rzeczą skrypt would sprawdzam ... tylko, że to nie zajdzie tak daleko. Zamiast tego, skrypt nie działa podczas kompilacji Pythona, zanim moje procedury są nawet wezwani. Tak więc użytkownik skryptu widzi kilka bardzo obscure SyNaX error tracebacks-które w zasadzie wymagają eksperta, aby wywnioskować, że jest to po prostu przypadek biegania zła wersja Pythona.

Wiem jak sprawdzić wersję Pythona. Problem polega na tym, że niektóre składnie są nielegalne w starszych wersjach Pythona. Rozważ ten program:

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

When run poniżej 2.4, chcę ten wynik

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

I nie ten wynik:

$ ~/bin/python2.4 tern.py 
  File "tern.py", line 5
    x = 1 if True else 2
           ^
SyntaxError: invalid syntax
/ Align = "center" bgcolor = "# e0ffe0 " / cesarz Chin / / align = center / )
Author: Martin Thoma, 2009-01-15

17 answers

Możesz przetestować używając eval:

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

Także, with jest dostępne w Pythonie 2.5, wystarczy dodać from __future__ import with_statement.

EDIT: aby uzyskać kontrolę wystarczająco wcześnie, możesz podzielić ją na różne pliki .py i sprawdzić zgodność w głównym pliku przed zaimportowaniem (np. w __init__.py w pakiecie):

# __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 *
 104
Author: orip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-31 15:35:48

Mieć owijkę wokół programu, który wykonuje następujące czynności.

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

Możesz również rozważyć użycie sys.version(), jeśli planujesz spotkać ludzi, którzy używają interpreterów Pythona sprzed wersji 2.0, ale musisz zrobić kilka wyrażeń regularnych.

I mogą być bardziej eleganckie sposoby, aby to zrobić.
 102
Author: Ed Carrel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 17:45:44

Try

import platform
platform.python_version()

Powinno dać ci ciąg znaków jak "2.3.1". Jeśli nie jest to dokładnie to, czego chcesz, istnieje bogaty zestaw danych dostępnych za pośrednictwem wbudowanej "platformy". To, czego chcesz, powinno gdzieś tam być.

 28
Author: James Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-15 09:08:12

Prawdopodobnie najlepszym sposobem na porównanie tej wersji jest użycie sys.hexversion. Jest to ważne, ponieważ porównywanie krotek wersji nie da pożądanego rezultatu we wszystkich wersjach Pythona.

import sys
if sys.hexversion < 0x02060000:
    print "yep!"
else:
    print "oops!"
 21
Author: sorin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-28 12:38:59
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")
 15
Author: Erick Wendel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-15 19:32:40

Odpowiedź od Nykakina w AskUbuntu :

Możesz również sprawdzić wersję Pythona z samego kodu za pomocą modułu platform z biblioteki standardowej.

Istnieją dwie funkcje:

  • platform.python_version() (zwraca łańcuch).
  • platform.python_version_tuple() (zwraca krotkę).

Kod Pythona

Utwórz plik na przykład: version.py)

Łatwa metoda sprawdzania wersji:

import platform

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

Możesz również użyć eval "metoda": {]}

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

Uruchom plik Pythona w wierszu poleceń:

$ python version.py 
2.7.11
('2', '7', '11')
W przeciwieństwie do Pythona, Python nie jest używany w systemach Windows 10.]}

Zrzut ekranu 2016-11-16 14.39.01 przez Suriyaa Kudo


Pomocne zasoby

 9
Author: Suriyaa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 22:09:37

Sets stał się częścią języka Core w Pythonie 2.4, aby zachować kompatybilność wsteczną. Zrobiłem to wtedy, co będzie działać również dla ciebie:

if sys.version_info < (2, 4):
    from sets import Set as set
 7
Author: André,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 17:46:38

Chociaż pytanie jest: Jak uzyskać kontrolę wystarczająco wcześnie, aby wydać komunikat o błędzie i zakończyć?

Pytanie, na które odpowiadam jest: Jak uzyskać kontrolę wystarczająco wcześnie, aby wydać komunikat o błędzie przed uruchomieniem aplikacji?

Mogę na to odpowiedzieć dużo inaczej niż na innych postach. Wygląda na to, że odpowiedzi do tej pory próbują rozwiązać twoje pytanie z poziomu Pythona.

Mówię, aby sprawdzić wersję przed uruchomieniem Pythona. Widzę, że Twoja ścieżka jest Linux czy unix. Jednak mogę zaoferować tylko skrypt systemu Windows. Adaptacja go do składni skryptów Linuksa nie byłaby zbyt trudna.

Oto skrypt DOS w wersji 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

To nie uruchamia żadnej części twojej aplikacji i dlatego nie spowoduje wywołania wyjątku Pythona. Nie tworzy żadnego pliku tymczasowego ani nie dodaje żadnych zmiennych środowiskowych Systemu Operacyjnego. I to nie kończy aplikacji do wyjątku ze względu na różne reguły składni wersji. To trzy mniej możliwych punktów bezpieczeństwa dostęp.

Linia FOR /F jest kluczem.

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

Dla wielu wersji Pythona Sprawdź adres URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17

I moja wersja hack:

[ms script; wersja Pythona sprawdź prelaunch modułu Pythona] http://pastebin.com/aAuJ91FQ

 7
Author: DevPlayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-02 03:39:26

Jak wspomniano powyżej, Błędy składniowe występują podczas kompilacji, a nie podczas uruchamiania. Podczas gdy Python jest "językiem interpretowanym", Kod Pythona nie jest w rzeczywistości interpretowany bezpośrednio; jest kompilowany do kodu bajtowego, który jest następnie interpretowany. Istnieje krok kompilacji, który ma miejsce, gdy moduł jest importowany (jeśli nie ma już skompilowanej wersji dostępnej w formie a .pyc lub .plik pyd) i wtedy dostajesz swój błąd, a nie (całkiem dokładnie) kiedy twój kod jest uruchomiony.

Możesz odłożyć krok kompilacji i zrobić to w czasie wykonywania pojedynczej linii kodu, jeśli chcesz, używając eval, jak wspomniano powyżej, ale osobiście wolę tego unikać, ponieważ powoduje to, że Python wykonuje potencjalnie niepotrzebną kompilację w czasie wykonywania, z jednej strony, a z drugiej, tworzy to, co dla mnie czuje się jak bałagan w kodzie. (Jeśli chcesz, możesz wygenerować kod, który generuje kod, który generuje kod - i mieć absolutnie fantastyczny czas modyfikowania i debugowania, że w ciągu 6 miesięcy od teraz.) Więc to, co polecam zamiast tego, to coś bardziej takiego:
import sys
if sys.hexversion < 0x02060000:
    from my_module_2_5 import thisFunc, thatFunc, theOtherFunc
else:
    from my_module import thisFunc, thatFunc, theOtherFunc

.. co bym zrobił, nawet gdybym miał tylko jedną funkcję, która używała nowszej składni i była bardzo krótka. (W rzeczywistości podjąłbym wszelkie rozsądne środki, aby zminimalizować liczbę i rozmiar takich funkcji. Mogę nawet napisać funkcję jak ifTrueAElseB (cond, a, b) z tą pojedynczą linią składni w nim.)

Kolejną rzeczą, która może być warta zwrócenia uwagi (że jestem trochę zdumiona, że nikt jeszcze nie wskazał) jest to, że podczas gdy wcześniejsze wersje Pythona nie wspierały kodu jak

value = 'yes' if MyVarIsTrue else 'no'

.. obsługiwał Kod jak

value = MyVarIsTrue and 'yes' or 'no'
To był stary sposób pisania wyrażeń trójdzielnych. Nie mam jeszcze zainstalowanego Pythona 3, ale z tego, co wiem, Ten "stary" sposób działa do dziś, więc możesz sam zdecydować, czy warto warunkowo korzystać z nowej składni, jeśli potrzebujesz wspierać korzystanie ze starszych wersji Pythona.
 2
Author: Shavais,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-13 02:27:02

Umieść na samej górze pliku:

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)

Następnie kontynuuj z normalnym kodem Pythona:

import ...
import ...
other code...
 2
Author: jml,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 11:19:29
import sys
sys.version

Będzie otrzymywał odpowiedź w ten sposób

'2.7.6 (default, Oct 26 2016, 20:30:19) \n [GCC 4.8.4]"

Tutaj 2.7.6 is version

 2
Author: Janarthanan Ramu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-24 05:26:49

Myślę, że najlepszym sposobem jest przetestowanie funkcjonalności, a NIE wersji. W niektórych przypadkach jest to trywialne, a nie w innych.

Eg:

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

Dopóki jesteś wystarczająco konkretny w użyciu bloków try / except, możesz pokryć większość swoich baz.

 1
Author: sykora,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-15 08:51:22

Właśnie znalazłem to pytanie po szybkim wyszukiwaniu, próbując rozwiązać problem sam i wymyśliłem hybrydę na podstawie kilku powyższych sugestii.

Podoba mi się pomysł Devplayera na użycie skryptu wrappera, ale minusem jest to, że w końcu utrzymujesz wiele wrapperów dla różnych systemów operacyjnych, więc zdecydowałem się napisać wrapper w Pythonie, ale używam tej samej podstawowej logiki "chwyć wersję uruchamiając exe" i wpadłem na to.

Myślę, że powinno działać na 2.5 i naprzód. Testowałem go na 2.66, 2.7.0 i 3.1.2 na Linuksie i 2.6.1 na OS X do tej pory.

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

Tak, Wiem, że ostateczna linia dekodowania / paska jest okropna, ale chciałem szybko pobrać Numer wersji. Udoskonalę to.

To działa na razie wystarczająco dobrze dla mnie, ale jeśli ktoś może to poprawić (lub powiedzieć mi, dlaczego to okropny pomysł), to też byłoby fajne.

 1
Author: Steve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-09 16:11:57

Możesz sprawdzić za pomocą sys.hexversion lub sys.version_info.

sys.hexversion nie jest zbyt przyjazny dla człowieka, ponieważ jest liczbą szesnastkową. sys.version_info jest krotką, więc jest bardziej przyjazna człowiekowi.

Sprawdź dla Pythona 3.6 lub nowszego za pomocą 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()

Sprawdź dla Pythona 3.6 lub nowszego za pomocą 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 jest bardziej przyjazny dla człowieka, ale zajmuje więcej znaków. Polecam sys.hexversion, mimo że jest mniej przyjazny dla człowieka.

Mam nadzieję, że to wam pomogło!

 0
Author: Pb2007,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-27 19:26:55

Dla samodzielnych skryptów Python, poniższy moduł docstring trick do wymuszenia wersji Pythona (tutaj v2.7.X) działa (testowane na * 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
[...]

Powinno to również obsługiwać brakujący plik wykonywalny Pythona, ale ma zależność od grepa. Zobacz tutaj aby dowiedzieć się więcej.

 0
Author: akhan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-15 23:17:25

A może tak:

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
Author: Pb2007,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-23 00:12:01

Problem jest dość prosty. Sprawdziłeś czy wersja jest mniej niż 2.4, nie mniej niż lub równe. Więc jeśli wersja Pythona jest 2.4, to nie jest mniejsza niż 2.4. To co powinieneś mieć to:

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

, Nie

    if sys.version_info < (2, 4):
 -3
Author: Peter Mortensen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-12 17:48:06