2017-02-15 14 views
7

Co możemy umieścić w pliku setup.py, aby zapobiec gromadzeniu się pip i próbie instalacji pakietu przy użyciu nieobsługiwanej wersji Pythona?Zapobieganie instalowaniu pakietu na starych wersjach w języku Python

Na przykład magicstack jest projektem wymienione z klasyfikatora trove:

Programming Language :: Python :: 3 :: Only 

więc oczekiwać następującego zachowania jeśli pip --version jest przywiązany do Python 2.7:

$ pip install magicstack 
Collecting magicstack 
    Could not find a version that satisfies the requirement magicstack (from versions:) 
No matching distribution found for magicstack 

Ale rzeczywiste zachowanie jest, że pip zbiera wydanie, pobiera je, próbuje je zainstalować i kończy się niepowodzeniem. Są na przykład inne wydania tylko Python3, na przykład curio, które faktycznie instalują się dobrze - ponieważ setup.py nie używał niczego specyficznego dla Python 3 - tylko po to, by zawieść w czasie importu, gdy używana jest tylko składnia tylko Python 3. I jestem pewien, że istnieją pakiety, które instalują OK, importują OK, a może tylko kończą się niepowodzeniem!

Jaka jest poprawna metoda określania obsługiwanych wersji Pythona w sposób, który będzie respektowany przez pip? Znalazłem obejście problemu, obejmujące przesyłanie tylko pliku koła i odmowę przesłania dystrybucji .tar.gz, ale chciałbym poznać poprawną poprawkę.


Edit: Jak pip wiedzieć nie ściągnąć rozmieszczenia kół czy Python/os/architektura nie jest dopasowanie? Czy po prostu używasz .whl filename convention, czy jest coś bardziej wyrafinowanego niż to, co dzieje się za kulisami? Czy możemy w jakiś sposób przekazać metadane do dystrybucji źródłowej, aby pip zrobił to, co trzeba z plikami .tar.gz?

+0

nie wiem, że to jest odpowiedź _right_ ... ale jeśli 'magicstack' jest python3 tylko dlatego' setup.py' nie na python2.x, to wydaje się, że jednym z możliwych sposobów, aby ta praca jest zmusić twój plik 'setup.py' do błędu w nieodpowiednich wersjach pythona ... – mgilson

+0

Hacky. Jeśli pip jest powiązany z nieobsługiwanym interpreterem Pythona, nie chcę, aby pakiet był zbierany lub pobierany w ogóle, nie mówiąc już o próbie instalacji, wykonując 'setup.py'. – wim

+0

Google pojawia się jakiś [poprzedni] (http://stackoverflow.com/questions/13924931/setup-py-restrict-the-allowable-version-of-the-python-interpreter) [pytania] (http: // stackoverflow .com/questions/13385337/distribute-distutils-specify-python-version) z odpowiedziami mówiącymi, że twój plik 'setup.py' sprawdza wersję Pythona. – user2357112

Odpowiedz

3

Jest to poprawny sposób, aby to zrobić, ale niestety PIP zaczął go obsługiwać jedynie w wersji 9.0.0 (wydanej 2016-11-02), więc użytkownicy ze starszymi wersjami pip będą nadal pobierać pakiety chcąc nie chcąc niezależnie od wersji Pythona.

W pliku setup.py przechodzą setup() się python_requires argument, że wymienia swój pakiet jest obsługiwane wersje Pythona jako PEP 440version specifier. Na przykład, jeśli pakiet jest przeznaczony tylko dla Python 3+, napisz:

setup(
    ... 
    python_requires='>=3', 
    ... 
) 

Jeśli twoja paczka jest dla Pythona 3.3 i do góry, ale nie jesteś skłonny do popełniania do Pythona jeszcze 4 wsparcie, napisz:

setup(
    ... 
    python_requires='~=3.3', 
    ... 
) 

Jeśli pakiet jest dla Pythona 2.6, 2.7, a wszystkie wersje Pythona 3 wychodząc z 3,3, napisać:

setup(
    ... 
    python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4', 
    ... 
) 

I tak dalej.

Gdy to zrobisz, będziesz musiał zaktualizować swoją wersję setuptools do co najmniej 24.2.0, aby móc przetworzyć argument python_requires; wcześniejsze wersje po prostu zignorują to ostrzeżeniem. Następnie wszyscy twoi projektowi sdists i koła będą zawierały odpowiednie metadane, które podpowiedzą PyPI, aby poinformował nas o wersjach Pythona, dla których są przeznaczone.

+0

Cześć, dziękuję za aktualizację. Próbowałem Twojego rozwiązania, ale nie działa zgodnie z oczekiwaniami. Zaktualizowałem setuptools do wersji v34.3.2 i załadowałem nowe dystrybucje przy użyciu kwerendy 'python_requires'. W Pipsie wersji 9.0.1 w Pythonie 3.6 zachowanie jest ** poprawne ** (pip odmawia pobrania/uruchomienia dystrybucji i wypisuje wymagane/rzeczywiste wersje pythona). Jednak przy użyciu wersji PIP w wersji 9.0.1 w Pythonie 2.7, jest to niepoprawne - dystrybucja jest pobierana i wykonywany jest plik 'setup.py'. Wygląda na to, że istnieją odpowiednie metadane (ponieważ działa dla pip3), ale jest ignorowany przez pip2. Czy czegoś brakuje? – wim

+0

@wim: Jaki specyfikator wersji użyłeś do 'python_requires'? – jwodder

+0

Użyłem 'python_requires> = '3.6.1'' aby zastosować ograniczenie do metadanych, a następnie przetestowałem Plup 9.0.1 używając środowisk wirtualnych w 3.6.0 i 2.7.5. – wim

1

Rozkład magicstack na pypi jest uszkodzony. To się nie udaje, ponieważ dystrybucja źródłowa nie zawiera pakietu magicstack, mimo że setup.py dla dystrybucji źródłowej mówi, że powinien.

Dopóki PyPI zawiera źródła dystrybucji (np .tar.gz, .zip), PIP będzie pobierał że jeśli nie może znaleźć pasujący binarnej (np .egg, .whl) dla wersji Pythona/os/architektury.

Twoje opcje to wysyłanie dystrybucji binarnych tylko do pypi (najlepiej wheels), chociaż nie wiem nawet, czy dozwolone są pakiety pypi tylko dla binarnych. Inną opcją jest sprawdzenie, czy sys.version w twoim setup.py jest zgodny z wersjami i podnieść wyjątek w inny sposób.

+0

Przesyłanie wyłącznie dystrybucji binarnej jest dozwolone, o czym wspomniałem w moim pytaniu jako moje obecne obejście. Zobacz [toga-curses] (https://pypi.python.org/pypi/toga-curses/) na przykład pakietu, który zainstaluje się z pip3, ale nie będzie nawet widoczny przez pip2. – wim