Jeśli mam skrypt w języku Python, który wymaga co najmniej konkretnej wersji języka Python, jaki jest prawidłowy sposób, by upaść z wdziękiem, gdy do uruchomienia skryptu używana jest wcześniejsza wersja języka Python?
Jak uzyskać kontrolę wystarczająco wcześnie, aby wysłać komunikat o błędzie i wyjść?
Na przykład mam program, który używa operatora ternery (nowy w wersji 2.5) i „z” blokami (nowy w wersji 2.6). Napisałem prostą, małą procedurę sprawdzania wersji interpretera, która jest pierwszą rzeczą, którą skrypt mógłby wywołać ... tyle że nie zaszła tak daleko. Zamiast tego skrypt nie działa podczas kompilacji Pythona, zanim moje procedury zostaną nawet wywołane. W związku z tym użytkownik skryptu widzi pewne bardzo niejasne mechanizmy śledzenia błędów syx - które w zasadzie wymagają od eksperta wywnioskowania, że po prostu chodzi o uruchomienie niewłaściwej wersji 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
Gdy działa poniżej 2.4, chcę ten wynik
$ ~/bin/python2.4 tern.py
must use python 2.5 or greater
a nie ten wynik:
$ ~/bin/python2.4 tern.py
File "tern.py", line 5
x = 1 if True else 2
^
SyntaxError: invalid syntax
(Kanalizacja dla współpracownika.)
Odpowiedzi:
Możesz przetestować za pomocą
eval
:Ponadto,
with
jest dostępny w Pythonie 2.5, wystarczy dodaćfrom __future__ import with_statement
.EDYCJA: aby uzyskać kontrolę wystarczająco wcześnie, możesz podzielić ją na różne
.py
pliki i sprawdzić zgodność w głównym pliku przed importem (np. W__init__.py
pakiecie):źródło
exec
zamiasteval
. Wymyśliłem to podczas próby napisania funkcji, która wypisze na stderr zarówno py2k, jak i py3k.import
stacji w try / wyjątkiem). Pamiętaj, że może być konieczne sprawdzenie innych rzeczySyntaxError
(np. Wbudowanych funkcji lub dodatków do standardowej biblioteki)Mają opakowanie wokół programu, który wykonuje następujące czynności.
Możesz również rozważyć użycie
sys.version()
, jeśli planujesz spotkać ludzi, którzy używają interpreterów języka Python w wersjach wcześniejszych niż 2.0, ale wtedy musisz zrobić kilka wyrażeń regularnych.I mogą być bardziej eleganckie sposoby na zrobienie tego.
źródło
sys.version_info
nie jest funkcją.import this
. Urocza odmiana.Próbować
Powinien dać ci ciąg taki jak „2.3.1”. Jeśli nie jest to dokładnie takie, jak chcesz, istnieje bogaty zestaw danych dostępnych za pośrednictwem wbudowanej „platformy”. To, czego chcesz, powinno gdzieś tam być.
źródło
print(platform.python_version())
zamiastplatform.python_version()
!Prawdopodobnie najlepszym sposobem na porównanie tej wersji jest użycie
sys.hexversion
. Jest to ważne, ponieważ porównanie krotek wersji nie da pożądanego wyniku we wszystkich wersjach Pythona.źródło
źródło
sys.version_info
to nie nazwana krotki. Musisz użyćsys.version_info[0]
dla głównego numeru wersji isys.version_info[1]
dla mniejszego.Możesz również sprawdzić wersję Pythona z samego kodu za pomocą
platform
modułu ze standardowej biblioteki.Istnieją dwie funkcje:
platform.python_version()
(zwraca ciąg znaków).platform.python_version_tuple()
(zwraca krotkę).Kod Python
Łatwa metoda sprawdzenia wersji:
Możesz także użyć
eval
metody:Uruchom plik Python w wierszu polecenia:
Dane wyjściowe Pythona z CGI za pośrednictwem serwera WAMP w systemie Windows 10:
Pomocne zasoby
źródło
Zestawy stały się częścią podstawowego języka Python 2.4, aby zachować kompatybilność wsteczną. Zrobiłem to wtedy, co również zadziała dla ciebie:
źródło
try: set except NameError: from sets import Set as set
Chociaż pytanie brzmi: jak uzyskać kontrolę wystarczająco wcześnie, aby wysłać komunikat o błędzie i wyjść ?
Pytanie, na które odpowiadam brzmi: Jak uzyskać kontrolę wystarczająco wcześnie, aby wydać komunikat o błędzie przed uruchomieniem aplikacji ?
Mogę odpowiedzieć na to znacznie inaczej niż na inne posty. Wygląda na to, że jak dotąd odpowiedzi próbują rozwiązać twoje pytanie z poziomu Pythona.
Mówię, sprawdź wersję przed uruchomieniem Pythona. Widzę, że twoja ścieżka to Linux lub Unix. Mogę jednak zaoferować tylko skrypt systemu Windows. Wyobrażam sobie, że dostosowanie go do składni skryptów linuksowych nie byłoby zbyt trudne.
Oto skrypt DOS z wersją 2.7:
To nie uruchamia żadnej części twojej aplikacji i dlatego nie wywoła wyjątku Python. Nie tworzy żadnych plików tymczasowych ani nie dodaje żadnych zmiennych środowiskowych systemu operacyjnego. I to nie kończy twojej aplikacji na wyjątku z powodu różnych reguł składni wersji. To trzy mniej prawdopodobne punkty bezpieczeństwa dostępu.
The
FOR /F
Linia jest kluczem.W przypadku wielu wersji Pythona sprawdź adres URL: http://www.fpschultze.de/modules/smartfaq/faq.php?faqid=17
I moja wersja hacka:
[Skrypt MS; Sprawdzanie wersji Python przed uruchomieniem modułu Python] http://pastebin.com/aAuJ91FQ
źródło
dostanę taką odpowiedź
tutaj 2.7.6 jest wersją
źródło
Jak wspomniano powyżej, błędy składniowe występują w czasie kompilacji, a nie w czasie wykonywania. Podczas gdy Python jest „językiem interpretowanym”, kod Pythona nie jest w rzeczywistości bezpośrednio interpretowany; jest kompilowany do kodu bajtowego, który jest następnie interpretowany. Jest krok kompilacji, który ma miejsce, gdy moduł jest importowany (jeśli nie ma już skompilowanej wersji dostępnej w postaci pliku .pyc lub .pyd) i wtedy pojawia się błąd, a nie (całkiem dokładnie) kiedy Twój kod działa.
Możesz odłożyć krok kompilacji i sprawić, by stało się to w czasie wykonywania pojedynczego wiersza kodu, jeśli chcesz, używając eval, jak wspomniano powyżej, ale ja osobiście wolę tego unikać, ponieważ powoduje to, że Python może potencjalnie działać niepotrzebna kompilacja w czasie wykonywania, z jednej strony, a z drugiej, tworzy coś, co wydaje mi się bałaganem kodu. (Jeśli chcesz, możesz wygenerować kod, który generuje kod, który generuje kod - i mieć absolutnie fantastyczny czas na modyfikowanie i debugowanie tego za 6 miesięcy od teraz.) Więc zamiast tego poleciłbym coś takiego:
.. co zrobiłbym, nawet gdybym miał tylko jedną funkcję, która używałaby nowszej składni i była ona bardzo krótka. (W rzeczywistości podjąłbym wszelkie rozsądne środki, aby zminimalizować liczbę i rozmiar takich funkcji. Mógłbym nawet napisać funkcję taką jak ifTrueAElseB (cond, a, b) z tą pojedynczą linią składni.)
Kolejną rzeczą, na którą warto zwrócić uwagę (jestem trochę zaskoczony, że nikt jeszcze nie zauważył) jest to, że chociaż wcześniejsze wersje Pythona nie obsługiwały kodu takiego jak
.. obsługuje kod jak
To był stary sposób pisania wyrażeń potrójnych. Nie mam jeszcze zainstalowanego Pythona 3, ale o ile wiem, ten „stary” sposób nadal działa do dziś, więc możesz sam zdecydować, czy warto warunkowo użyć nowej składni, jeśli potrzebujesz do obsługi korzystania ze starszych wersji Pythona.
źródło
a and b or c
ob if a else c
, to nie jest równoważne; jeślib
jest fałszem, zawiedzie, produkując,a
a nieb
.Umieść u góry pliku następujące informacje:
Następnie przejdź do normalnego kodu Python:
źródło
sys.version_info < (2, 7)
sys.version_info
typu z krotką działa?sys.version_info
stosuje się krotki; na przykład(2, 4, 6, 'final', 0)
; tylko w Pythonie 3 i 2.7 został zmieniony na osobny typ, który jest jednak porównywalny z krotkami.Myślę, że najlepszym sposobem jest przetestowanie funkcjonalności, a nie wersji. W niektórych przypadkach jest to banalne, w innych nie.
na przykład:
Tak długo, jak jesteś wystarczająco zaawansowany w korzystaniu z bloków try / wyjątkiem, możesz pokryć większość swoich baz.
źródło
Właśnie znalazłem to pytanie po szybkim wyszukiwaniu, próbując samodzielnie rozwiązać problem, i opracowałem hybrydę opartą na kilku powyższych sugestiach.
Podoba mi się pomysł DevPlayera na użycie skryptu opakowania, ale wadą jest to, że ostatecznie utrzymujesz wiele opakowań dla różnych systemów operacyjnych, więc postanowiłem napisać opakowanie w pythonie, ale użyj tego samego podstawowego „pobierz wersję, uruchamiając exe” i wymyślił to.
Myślę, że powinno działać od wersji 2.5 i nowszych. Do tej pory przetestowałem go w wersjach 2.66, 2.7.0 i 3.1.2 w systemie Linux i 2.6.1 w systemie OS X.
Tak, wiem, że ostatnia linia dekodowania / stripowania jest okropna, ale chciałem tylko szybko pobrać numer wersji. Udoskonalę to.
Na razie działa mi to wystarczająco dobrze, ale jeśli ktoś może to poprawić (lub powiedzieć mi, dlaczego to okropny pomysł), to też byłoby fajne.
źródło
W przypadku samodzielnych skryptów Pythona działa następująca sztuczka docstring modułu w celu wymuszenia wersji Pythona (tutaj v2.7.x) (testowana na * nix).
Powinno to również obsługiwać brakujący plik wykonywalny Pythona, ale ma zależność od grep. Zobacz tutaj dla tła.
źródło
Możesz to sprawdzić za pomocą
sys.hexversion
lubsys.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 dla człowieka.Sprawdź Python 3.6 lub nowszy za pomocą
sys.hexversion
:Sprawdź Python 3.6 lub nowszy za pomocą
sys.version_info
:sys.version_info
jest bardziej przyjazny dla człowieka, ale wymaga więcej postaci. Polecamsys.hexversion
, choć jest mniej przyjazny dla człowieka.Mam nadzieję, że to ci pomogło!
źródło
Rozwijam doskonałą odpowiedź Akhana, która drukuje przydatną wiadomość przed skompilowaniem skryptu Python.
Jeśli chcesz się upewnić, że skrypt jest uruchamiany w Pythonie 3.6 lub nowszym, dodaj te dwa wiersze u góry skryptu Python:
(Uwaga: Drugi wiersz zaczyna się od czterech pojedynczych cudzysłowów, a kończy na trzech pojedynczymi cudzysłowami. Może to wyglądać dziwnie, ale nie jest to literówka.)
Zaletą tego rozwiązania jest to, że kod podobny
print(f'Hello, {name}!')
nie spowoduje,SyntaxError
że zostanie użyta wersja Python starsza niż 3.6. Zamiast tego zobaczysz tę pomocną wiadomość:Oczywiście to rozwiązanie działa tylko na powłokach uniksopodobnych i tylko wtedy, gdy skrypt jest wywoływany bezpośrednio (na przykład
./script.py
:) i przy ustawionych odpowiednich bitach uprawnień eXecute.źródło
Co powiesz na to:
źródło
Problem jest dość prosty. Sprawdziłeś, czy wersja była mniejsza niż 2,4, nie mniejsza niż lub równa . Więc jeśli wersja Pythona to 2.4, to nie mniej niż 2.4. Co powinieneś był mieć:
, nie
źródło