W przypadku konwersji kodu Python2 na Python3 Która wersja Python i Django najlepiej się nadaje?

11

Obecnie pracuję w dużej firmie, w której musimy przekonwertować stary duży projekt Django Pythona na wersję python3, więc przeprowadziłem wiele badań związanych z tym zagadnieniem, ale wciąż nie jestem w stanie znaleźć idealnej odpowiedzi na pytanie, która wersja Python i Django najlepiej nadaje się do konwersji.

Obecnie używam Python: 2.7.16 i Django: 1.9.13 w mojej starej wersji.

Każdy może zasugerować mi najlepiej pasującą wersję Pythona i Django dla starszych wersji dla konwersji python2 na python3.

Księżyc
źródło
Obecna wersja Python3 to Python 3.8, a najnowsza wersja Django to Django 3.0. Witryna Django zaleca najnowszą wersję Pythona 3 , czyli 3.8. Czy jest jakiś szczególny powód, dla którego nie chcesz przyspieszać zarówno Pythona, jak i Django do ich najnowszych wersji?
Guy Green Cloak,
2
Anegdotycznie dopiero kilka dni temu zdałem sobie sprawę, że strona internetowa oparta na Django, którą prowadzę od kilku lat, faktycznie działa na serwerze, na którym działa na Python2.7, podczas gdy ja działam lokalnie za pomocą Python3. 7 Jedyną różnicą, jaką znalazłem, było to, że po raz pierwszy użyłem gdzieś f-stringów i wersja serwera uległa awarii; w przeciwnym razie działałby dokładnie zgodnie z oczekiwaniami (dokładnie tak samo) lokalnie i zdalnie, do celów testowania i dodawania funkcji. Mój całkowicie anegdotyczny wniosek jest taki, że Django jest ogólnie kompatybilny z większością rzeczy.
Guy Green Cloak,
1
w najnowszej wersji zauważyłem, że niektórzy ludzie nie zalecają, ponieważ w najnowszej wersji, jeśli mają jakieś nowe aktualizacje związane z problemami, czasami trudno będzie znaleźć rozwiązanie, więc w obecnym projekcie nie chcę robić takiego ryzyka, a także dla testując cel, zacząłem konwertować mój projekt do najnowszej wersji Pythona 3.7.3 z najnowszym django i już znalazłem 30 rodzajów problemów.
Księżyc
Należy zauważyć - to pytanie pojawiło się w moim przeglądzie przeglądowym. „Czy jest jakiś dokument lub odniesienie” jest bardzo nie na temat (proszenie o zasoby poza witryną). Uważam jednak, że pytanie można edytować w taki sposób, aby lepiej prowadziło do zaakceptowanej odpowiedzi poniżej.
maja

Odpowiedzi:

3

Pomyślałem, że dodam trochę do strategii zalecanej przez odpowiedź Wima - najpierw zdobądź odpowiednią wersję Django działającą na wersjach 2.7 i 3.x - i opisz kilka taktyk, które działały dla mnie.

Python 2.7 jest twoją kapsułą ratunkową, dopóki nie pociągniesz za spust w 3.x

  • twoje testy powinny działać na obu
  • nie używaj żadnych specyficznych funkcji 3.x, takich jak struny F.
  • najpierw Python 3.x, a dopiero później Django 2.x, który nie działa w wersji 2.7
  • zacznij wcześnie, nie analizuj zbytnio, ale unikaj podejścia wielkiego wybuchu
    • plik po pliku na początku.
    • zacznij od kodu najniższego poziomu, takiego jak biblioteki narzędziowe, dla których masz zestawy testowe.
    • jeśli to możliwe, spróbuj stopniowo scalać zmiany w gałęziach produkcyjnych 2.7 i dbać o to, aby Twój kod wersji 3.x był aktualizowany o zmiany prod.

Od jakiej małej wersji Django zacząć?

Moje kryterium jest takie, że migracje Django mogą być dość zaangażowane (i faktycznie wymagają więcej myślenia niż 2 => 3 pracy). Chciałbym przejść do najnowszej i najlepszej wersji 1.11 w ten sposób, że już zapewniasz pewną wartość swoim użytkownikom w wersji 2.7. Prawdopodobnie istnieje duża liczba podkładek kompatybilnych przed wersją 2.x na 1.11 i otrzymasz ostrzeżenia o wycofaniu 2.x.

Od jakiej małej wersji Python 3.x na początek?

Najlepiej jest wziąć pod uwagę wszystkie aspekty, takie jak dostępność bibliotek stron trzecich, wsparcie z pakietu CI / devops i dostępność na wybranych obrazach systemu operacyjnego serwera. Zawsze możesz na przykład zainstalować wersję 3.8 i samodzielnie wypróbować instalację PIP wymagań.txt.

Wykorzystaj git (lub inny scm, którego używasz) i virtualenv .

  • oddzielny requirement.txt pliki, ale ...
  • jeśli masz oparte na plikach, git repo, możesz skierować każdy venv na tę samą linię kodową za pomocą pip install -e <your directory>. oznacza to, że w 2 różnych terminalach możesz uruchamiać 2.7 i 3.x przeciwko tym samym unittest (s).
  • możesz nawet uruchomić serwery Django 2.7 i 3.x obok siebie na różnych portach i wskazać na nich Firefox i Chrome.
  • często zatwierdzaj (przynajmniej na gałęzi portującej) i dowiedz się o git bisect .

zrobić użytek z 2to3

Tak, złamie kod 2.7 i Django, jeśli na to pozwolisz. Więc...

  • uruchom go w trybie podglądu lub na jednym pliku. zobacz, co się psuje, ale także zobacz, co zrobiło dobrze.

  • ogranicz go tylko do niektórych konwersji, które nie łamią wersji 2.7 lub Django. print x=> print (x)i except(Exception) as esą 2 bezmyślnymi.

Tak wyglądało moje zdławione polecenie:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
  • uruchamiaj plik po pliku, aż będziesz naprawdę pewny siebie.

używaj sed lub awk zamiast edytora do konwersji zbiorczych.

Zaletą jest to, że gdy stajesz się bardziej świadomy obaw związanych ze swoimi aplikacjami, możesz zbudować zestaw zmian, które można uruchomić na jednym pliku lub wielu plikach i wykonać większość pracy bez złamania wersji 2.7 lub Django. Zastosuj to po odpowiednio przepustnicy 2 do 3 . To pozostawia resztki porządków w edytorze i pozwala przejść testy.

(opcjonalnie) zacznij wyświetlać czarny kod 2.7.

czarny, który jest formatatorem kodu, używa Pythona 3 AST do uruchomienia analizy. Nie próbuje uruchomić kodu, ale oznaczy błędy składniowe, które uniemożliwiają mu przejście do etapu AST. Będziesz musiał jednak popracować nad globalną magią instalacji, aby się tam dostać, i musisz kupić użyteczność czarnych.

Inni to zrobili - ucz się od nich.

Słuchanie # 155 Praktyczne kroki do przejścia na Python 3 powinny dać ci kilka pomysłów na temat pracy. Spójrz na linki do niego. Uwielbiają mówić o ruchu na Instagramie (?), Który polegał na stopniowym dostosowywaniu działania kodu 2.7 do składni 3.x na wspólnej bazie kodu i na tej samej gałęzi git, aż do dnia uruchomienia.

Zobacz też The Conservative Python 3 Porting Guide

a Instagram płynnie przechodzi do Pythona 3 - Nowy stos

Wniosek

Twój czas na Django 1.11 EOL (kwiecień 2020) jest raczej krótki, więc jeśli masz do dyspozycji ponad 2 zasoby deweloperskie, rozważę wykonanie następujących czynności równolegle:

  • DEV # 1: zacznij od wypukłości Django 1.11 (zgodnie z teorią, że Django 1.11 jest prawdopodobnie najlepiej ustawiony jako punkt wyjścia do Django 2.x), używając 2.7.

  • DEV # 2: zacznij na Pythonie 3.6 / 3.7 swojego kodu narzędzia innego niż Django. Ponieważ kod jest w tym momencie kompatybilny z wersją 2.7, scal go z numerem 1 w miarę upływu czasu.

Zobacz, jak przebiegają oba zadania, oceń ryzyko związane z projektem Django i jak wygląda ból w Pythonie 3. Już brakuje EOL języka Python 2.7, ale przestarzała platforma internetowa jest prawdopodobnie bardziej niebezpieczna niż starsza wersja Python 2.7, przynajmniej przez kilka miesięcy. Nie będę więc długo czekać na migrację z Django 1.9, a twoja praca nie będzie zmarnowana. Gdy zobaczysz postęp, zaczniesz lepiej widzieć ryzyko związane z projektem.

Początkowy postęp 2 do 3 będzie powolny, ale oprzyrządowanie i wskazówki są na tyle dobre, że szybko przyspieszysz, więc nie zastanawiaj się nad nim, zanim zaczniesz zbierać doświadczenia. Strona Django zależy od tego, czy jesteś narażony na przełomowe zmiany w frameworku, dlatego myślę, że najlepiej zacząć od początku.

PS (kontrowersyjne / osobiste zdanie) Nie użyłem sześciu używałem zbyt często lub innych puszkowanych bibliotek mostowych 2 do 3.

To nie dlatego, że nie ufa - to genialna na 3rd bibliotekami partii - ale raczej, że nie chcą, aby dodać kompleksową stałą zależność (a byłem zbyt leniwy, aby przeczytać jego doc). Długo pisałem kod 2.7 w składni zgodnej z 3.x, więc tak naprawdę nie czułem potrzeby ich używania. Twój przebieg może się różnić i nie zaczynaj na tej ścieżce, jeśli wydaje się, że to dużo pracy .

Zamiast tego stworzyłem py223.py (57 LOC wraz z komentarzami) z tego rodzaju treściami, z których większość dotyczy obejść przestarzałości i zmian nazw w standardowej bibliotece.

try:
    basestring_ = basestring
except (NameError,) as e:
    basestring_ = str

try:
    cmp_ = cmp
except (NameError,) as e:
    # from http://portingguide.readthedocs.io/en/latest/comparisons.html
    def cmp_(x, y):
        """
        Replacement for built-in function cmp that was removed in Python 3
        """
        return (x > y) - (x < y)

Następnie zaimportuj z tego py223, aby obejść te konkretne problemy. Później będzie tylko rów import i przenieść te dziwnie isinstance(x, basestr_)się isinstance(x, str)ale wiem z góry nie ma się czym martwić.

JL Peyret
źródło
Dobra rada. Tylko jedna uwaga, sam Django już używa sixwarstwy kompatybilności, więc jeśli chcesz użyć jej w projekcie Django podczas przejścia, nie oznacza to „dodawania złożonej stałej zależności”.
wim
@wim. Zgadzam się z tobą. sześć, ale zależy to od punktu widzenia. Już zauważyłem, że jest dostarczany z bibliotekami stron trzecich, więc nie „kosztuje” pod względem wymagań i ogólnych zależności. jednak ja - być może niesłusznie - uznałem to za dużą czarną skrzynkę / brodawkę w środku mojego kodu. jeśli wszystko, co robisz, to testowanie łańcucha instancji / unicode / basestring i jeśli wiesz, jak to zrobić sam, to wiesz dokładnie, jak wycofać podkładki, gdy nie są już potrzebne. Przeniosę to jednak do końca.
JL Peyret,
To pip install -e ...(z małą literą -e), prawda?
thebjorn,
prawdopodobnie tak jest. poprawi
JL Peyret
3

Moja propozycja to najpierw uaktualnić do Django==1.11.26 , która jest najnowszą wersją Django, która obsługuje zarówno Python 2, jak i Python 3. Na razie pozostań na aktualnej wersji Python 2.7.

Przeczytaj uważnie informacje o wersji 1.10.xi 1.11.x, sprawdzając, czy nie są one wycofywane i naprawiając wszystko, co przestało działać w kodzie 1.9.x. Rzeczy się zepsują. Django porusza się szybko. W przypadku dużego projektu Django może być wymaganych wiele zmian kodu, a jeśli używasz wielu wtyczek lub bibliotek innych firm, być może będziesz musiał żonglować ich wersjami. Niektóre z twoich zależności zewnętrznych prawdopodobnie zostaną całkowicie porzucone, więc musisz znaleźć zamienniki lub usunąć funkcje.

Aby znaleźć informacje o wersji dla każdej aktualizacji wersji, po prostu google „Co nowego w Django”. Trafienia dokładnie dokumentują wszystkie wycofania i zmiany:

Po webapp wydaje się być w porządku pracy na Django 1.11, przy przejściu wszystkich testów (Ci zrobić mieć zestaw testowy, prawda?), To można zrobić konwersję Python 3, utrzymując wersji Django samo. Django 1.11 obsługuje do Pythona 3.7, więc byłaby to dobra wersja docelowa. Spodziewaj się Unicode w dowolnym miejscu, ponieważ ukryte konwersje między bajtami a tekstem już minęły, a wiele aplikacji internetowych Python 2 polegało na tym.

Gdy projekt wydaje się działać poprawnie na Django 1.11 i Python 3.7, możesz pomyśleć o uaktualnieniu do Django 3.0, postępując tak samo jak poprzednio - czytając informacje o wersji, wprowadzając niezbędne zmiany, uruchamiając pakiet testowy i sprawdzając webapp na serwerze deweloperskim ręcznie.

wim
źródło
1
Zdecydowanie droga. Uruchom kod testowy w wersjach 2.7 i 3.x. Możesz mieć 2 różne virtualenvs wskazujące na to samo repozytorium git pip install -E. Po uruchomieniu testów jednostkowych rozpocznij testowe użycie Django-on-3x i ponownie utrzymuj kod działający w 2 i 3. Z ostrożnym kodowaniem i uważaniem, aby nie spalić twoich mostów 2.7 - na przykład żadnych ciągów - przełączenie będzie bardzo antyklimatyczne. Gdy wersja 3.x będzie całkowicie stabilna, zacznij używać tylko kodu 3.x. Zaletą jest to, że produkcja 2.7 jest zawsze w fazie aż do zmiany.
JL Peyret,
2

Najpierw uaktualnię do py3. Musisz zajrzeć setup.pydo repozytorium Django w gałęzi stable / 1.9.x ( https://github.com/django/django/blob/stable/1.9.x/setup.py ), aby dowiedzieć się, że py3 obsługiwane wersje to 3.4 (martwe) i 3.5.

Po przejściu na py3.5 i Django 1.9 możesz aktualizować pojedynczo, aż dojdziesz do wersji, na której chcesz zakończyć. Np. Django 1.11 obsługuje py3.5 i py3.7, więc

py27/dj19 -> py35/dj19 -> py35/dj1.11 -> py37/dj1.11 ... -> py37/dj2.2

dj2.2 to pierwsza wersja obsługująca py3.8, ale prawdopodobnie zatrzymałbym się na py37 / dj2.2, jeśli pracujesz w normalnie konserwatywnym środowisku.

Jeśli masz inne pakiety, musisz znaleźć kombinacje wersji, które będą działać razem na każdym kroku. Posiadanie planu jest kluczowe, a uaktualnianie tylko jednego elementu na raz zazwyczaj kończy się na oszczędności czasu.

Przyszła biblioteka ( https://python-future.org/ ) pomoże ci w wielu trudnych sytuacjach, gdy potrzebujesz kodu do uruchamiania zarówno na py27, jak i 3.x. sześć też jest świetne. Unikałbym zrolowania własnej warstwy kompatybilności (po co wymyślać koło?)

Jeśli to w ogóle możliwe, spróbuj uzyskać zasięg testu jednostkowego do 75-85% przed rozpoczęciem i zdecydowanie skonfiguruj automatyczne testowanie zarówno dla wersji „z”, jak i „do” dla każdego kroku aktualizacji. Upewnij się, że przeczytałeś i naprawiłeś wszystkie ostrzeżenia z Django przed aktualizacją do następnej wersji - Django bardzo nie dba o kompatybilność wsteczną, więc normalnie sugerowałbym trafienie w każdą mniejszą wersję na ścieżce aktualizacji (lub przynajmniej przeczytanie „wstecz” niezgodności ”i listy przestarzałych wersji dla każdej mniejszej wersji).

Powodzenia (aktualizujemy teraz bazę kodu Kloc 300 + z py27 / dj1.7, więc czuję twój ból ;-)

thebjorn
źródło
1
+1 przy pokryciu testowym. To kluczowa miara tutaj, bez względu na to, jakie podejście się skończy. To naprawdę pomaga w eksperymentowaniu ze wszechobecnymi zmianami kodu i mówię to jako ktoś, kto wcale nie jest miłośnikiem testów TDD Red / Green. Wymyśl sposób na bazowe wyniki 2.7, a aktualizacja stanie się o wiele łatwiejsza.
JL Peyret
2

Mam ten sam problem z moim projektem i wypróbowałem Python 3.7.5 w wersji Django 2.2.7.

Nie powinieneś używać najnowszej wersji Pythona 3.8 lub najnowszej wersji Django 3.0, ponieważ być może istniały szanse, że w przypadku jakiegokolwiek rodzaju błędu możesz nie być w stanie uzyskać odpowiedniego rozwiązania dla najnowszych wersji.

Alpesh
źródło
To powinien być komentarz
Bruno,
-2

Powinieneś spróbować strzelać do aktualnych wersji. Python 3.8 i Django 3.0. Sześć bibliotek pomoże wprowadzić pewne zmiany konwencji. Tak czy inaczej, będziesz musiał dokonać refaktoryzacji, aby równie dobrze uczynić to aktualnym.

Dave
źródło
3
Czy kiedykolwiek zrobiłeś aktualizację Django? To tylko pobożne życzenie. Przejście bezpośrednio do Pythona 3.8 i Django 3.0 z wersji 2.7 / 1.9 będzie praktycznie niemożliwe. Nawet aktualizacja mniejszych wersji, takich jak Django 1.9 do 1.10, może być trudnym procesem, wymagającym wielu zmian w kodzie.
wim
Tak, pod warunkiem, że otrzymałem luksus i pozwolenie na czas, aby wykonać pełny refaktor i zaktualizować aplikację. Znowu rozmiar aplikacji, logika i ograniczenia czasowe są ogromnym problemem dla większości facetów, ale nigdy nie wspominali o rozmiarze aplikacji lub ograniczeniu czasowym, więc zaleciłem moją opinię o „najlepszym rozwiązaniu” lub „pobożnym życzeniu”;)
Dave
dodatkowo, jeśli musisz się martwić o rzeczy Odpowiedzialne i działające również na LTS Ubuntu, przekonasz się, że w Ubuntu 18.04 brakuje nawet 3,7 wsparcia. Podcasty na temat bezpieczeństwa, których słucham, zalecam, aby pozwolenie 3.8 nieco się uspokoiło do momentu zwolnienia punktu lub 2. -1 za niepotrzebne ryzyko.
JL Peyret,
Jakieś dobre rekomendacje podcastów dotyczących bezpieczeństwa?
Dave
W przypadku Pythona sec, listennotes.com/podcasts/talk-python-to-me/… Ale myślę, że uważaj na wersję 3.8 na jakiś czas jest nowsza. Risky Business to dobry i zabawny podcast na temat bezpieczeństwa, szczególnie jeśli stosujesz się do stosunków międzynarodowych. Przepraszam za przegłosowanie, ale tak, to, co zadziałało w twoim przypadku, może zmiażdżyć kogoś innego w innym kontekście. Aby przekonwertować konwersję 2 na 3, patrz listennotes.com/podcasts/talk-python-to-me/…
JL Peyret