Per la conversione del codice da Python2 a Python3, quale versione di Python e Django è più adatta?


11

Attualmente sto lavorando in una grande azienda dove abbiamo bisogno di convertire il vecchio grande progetto Django python2 in versione python3, quindi ho fatto molte ricerche relative ma ancora non sono riuscito a trovare una risposta perfetta in relazione alla versione di Python e Django più adatta alla conversione.

Attualmente sto usando Python: 2.7.16 e Django: 1.9.13 nella mia vecchia versione.

Chiunque può suggerirmi la versione più adatta di Python & Django per la versione precedente sopra per la conversione da python2 a python3.


La versione corrente di python3 è Python 3.8 e l'ultima versione di Django è Django 3.0. Il sito Web di Django consiglia l'ultima versione di Python 3 , che è la 3.8. C'è un motivo particolare per cui non vuoi accelerare sia Python che Django alle loro versioni più recenti?
Green Cloak Guy

2
Aneddoticamente, mi sono reso conto solo pochi giorni fa che il sito Web basato su Django che gestisco da alcuni anni ora funziona sul server su cui è ospitato usando python2.7, mentre lo ho eseguito localmente usando python3. 7. L'unica differenza che ho riscontrato è stata quando ho provato a utilizzare f-string da qualche parte per la prima volta e la versione del server web si è bloccata; altrimenti è stato eseguito esattamente come previsto (esattamente lo stesso) localmente e da remoto, a scopo di test e aggiunta di funzionalità. La mia conclusione totalmente aneddotica è che Django è generalmente compatibile con la maggior parte delle cose.
Green Cloak Guy

1
per l'ultima versione, ho scoperto che alcune persone non lo consigliano perché nella versione più recente in caso di problemi relativi a nuovi aggiornamenti, sarà difficile trovare una soluzione a volte, quindi nel progetto corrente non voglio fare questo tipo di rischio e anche per scopo del test, ho iniziato a convertire il mio progetto in Python 3.7.3 ultima versione con l'ultimo django e ho già riscontrato 30 tipi di problemi.
Luna,

Va notato - questa domanda è emersa in un audit di revisione per me. "Esiste un documento o un riferimento" è chiaramente fuori tema (chiedendo una risorsa fuori sede). Tuttavia, credo che la domanda potrebbe essere modificata in modo tale da poter portare meglio alla risposta accettata di seguito.
theMayer

Risposte:


3

Ho pensato di aggiungere un po 'alla strategia sostenuta dalla risposta di Wim: far funzionare prima la versione appropriata di Django su 2.7 e 3.x e delineare alcune tattiche che hanno funzionato per me.

Python 2.7 è il tuo pod di escape, fino a quando non premi il grilletto su 3.x.

  • i tuoi test dovrebbero essere eseguiti su entrambi
  • non utilizzare alcuna funzionalità specifica 3.x, come f-string
  • prima Python 3.x, poi solo successivamente Django 2.x che non funziona su 2.7
  • iniziare presto, non analizzare troppo, ma evitare l'approccio big bang
    • file per file all'inizio.
    • iniziare con il codice di livello più basso, come le librerie di utilità, per cui si dispone di suite di test.
    • se possibile, prova a unire gradualmente le tue modifiche ai rami di produzione 2.7 e mantieni aggiornato il tuo codice di porting 3.x con le modifiche prod.

Con quale versione minore di Django iniziare?

I miei criteri qui sono che le migrazioni di Django possono essere abbastanza coinvolte (e in realtà richiedono più pensiero di 2 => 3 lavori). Quindi passerei all'ultima e la più grande 1.11 in questo modo stai già fornendo un valore ai tuoi utenti 2.7. Probabilmente c'è un buon numero di spessori di compatibilità pre-2.x su 1.11 e riceverai i suoi avvisi di deprecazione 2.x.

Con quale versione minore di Python 3.x iniziare?

È meglio considerare tutti gli angoli, come la disponibilità delle librerie di terze parti, il supporto dalla suite CI / devops e la disponibilità sulle immagini del sistema operativo del server prescelte. Puoi sempre installare 3.8 e provare un'installazione pip del tuo requisito.txt da solo, per esempio.

Sfrutta git (o qualsiasi altra cosa tu usi) e virtualenv .

  • requirement.txtfile separati , ma ...
  • se si dispone di un repository git basato su file, è possibile puntare ogni venv alla stessa codeline con a pip install -e <your directory>. ciò significa che, in 2 terminali diversi, è possibile eseguire 2.7 e 3.x contro gli stessi unittest (s).
  • potresti persino eseguire server Django 2.7 e 3.x fianco a fianco su porte diverse e puntare su Firefox e Chrome.
  • impegnarsi spesso (almeno sul ramo porting) e conoscere git bisect .

fare uso di 2to3

Sì, si romperà il codice 2.7 e Django se lo si lascia. Così...

  • eseguirlo in modalità anteprima o su un singolo file. vedere cosa si rompe ma anche vedere cosa ha fatto bene.

  • limitalo a determinate conversioni che non infrangono la 2.7 o Django. print x=> print (x)e except(Exception) as esono 2 senza cervello.

Ecco come appariva il mio comando strozzato:

2to3 $tgt -w -f except -f raise -f next -f funcattrs -f print
  • eseguilo file per file fino a quando non sei davvero sicuro.

usa sed o awk anziché il tuo editor per conversioni collettive.

Il vantaggio è che, man mano che diventi più consapevole delle preoccupazioni specifiche delle tue app, puoi creare una suite di modifiche che possono essere eseguite su 1 o più file e svolgere la maggior parte del lavoro senza rompere 2.7 o Django. Applicare questo dopo il vostro opportunamente strozzato 2to3 pass. Questo ti lascia con le pulizie residue nel tuo editor e fa passare i test.

(facoltativo) inizia a funzionare in nero con il codice 2.7.

black, che è un formattatore di codice, utilizza AST Python 3 per eseguire la sua analisi. Non tenta di eseguire il codice, ma contrassegnerà gli errori di sintassi che gli impediscono di raggiungere lo stadio AST. Dovrai lavorare con qualche pip per installare la magia globale per arrivarci e devi acquistare l'utilità del nero.

Altre persone l'hanno fatto - impara da loro.

Ascolto del numero 155 I passaggi pratici per passare a Python 3 dovrebbero darti alcune idee sul lavoro. Guarda i link dello spettacolo per questo. Amano parlare della mossa di Instagram (?) Che ha comportato una graduale regolazione dell'esecuzione del codice 2.7 sulla sintassi 3.x su una base di codice comune e sullo stesso ramo git, fino al giorno del grilletto.

Vedi anche The Conservative Python 3 Porting Guide

e Instagram passa a Python 3 : il nuovo stack

Conclusione

Il tuo tempo a Django 1.11 EOL (aprile 2020) è piuttosto breve, quindi se hai 2+ risorse di sviluppo da lanciare, prenderei in considerazione la seguente procedura in parallelo:

  • DEV # 1: inizia con un bump di Django 1.11 (la teoria è che Django 1.11 è probabilmente il miglior punto di partenza per Django 2.x), usando 2.7.

  • DEV # 2: inizia su Python 3.6 / 3.7 del tuo codice di utilità non Django. Poiché il codice è 2.7 compatibile a questo punto, uniscilo al n. 1 mentre procedi.

Guarda come procedono entrambe le attività, valuta qual è il rischio del progetto relativo a Django e come si presenta il dolore di Python 3. Ti manca già l'EOL di Python 2.7, ma un framework Web obsoleto è probabilmente più pericoloso del precedente Python 2.7, almeno per alcuni mesi. Quindi non aspetterei troppo a lungo per iniziare a migrare da Django 1.9 e il tuo lavoro non sarà sprecato. Man mano che vedi i progressi, inizierai a vedere meglio i rischi del progetto.

I tuoi progressi iniziali 2to3 saranno lenti, ma gli strumenti e la guida sono abbastanza buoni da farti guadagnare rapidamente velocità, quindi non pensarci troppo prima di iniziare a raccogliere esperienza. Il lato di Django dipende dalla tua esposizione a cambiamenti radicali nel framework, motivo per cui penso sia meglio iniziare presto.

PS (opinione controversa / personale) Non ho usato molto sei o altre librerie di bridge da 2 a 3 in scatola.

E ' non è perché non mi fido - è brillante per 3rd librerie di partito - ma piuttosto che non volevo aggiungere un complesso di dipendenza permanente (e io ero troppo pigro per leggere il suo doc). Avevo scritto il codice 2.7 nella sintassi compatibile 3.x per molto tempo, quindi non sentivo davvero il bisogno di usarli. Il tuo chilometraggio può variare e non intraprendere questo percorso se sembra un sacco di lavoro .

Invece, ho creato un py223.py (57 LOC incl. Commenti) con questo tipo di contenuto, la maggior parte dei quali riguarda soluzioni alternative per ammortamenti e cambi di nome nella libreria standard.

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)

Quindi importare da quel py223 per aggirare quelle preoccupazioni specifiche. In seguito mi limiterò a scavare l'importazione e spostare quegli strani isinstance(x, basestr_)a isinstance(x, str)ma so in anticipo c'è poco di cui preoccuparsi.


Buon Consiglio. Solo una nota, Django stesso utilizza già sixper il livello di compatibilità, quindi se si desidera utilizzarlo in un progetto Django durante la transizione, non si tratta di "aggiungere una dipendenza permanente complessa".
mercoledì

@wim. Sono d'accordo con te riguardo. sei, ma dipende dal punto di vista. Ho già notato che viene fornito con librerie di terze parti, quindi non "costa" in termini di requisiti e dipendenze complessive. tuttavia, forse - a torto - l'ho considerata una grande scatola nera / verruca nel mezzo del mio codice. se tutto ciò che fai sono cose come testare l'istanza stringa / unicode / basestring e se sai come farlo da solo, allora sai esattamente come sostenere gli shim quando non sono più necessari. Lo sposterò fino alla fine, però.
JL Peyret,

È pip install -e ...(con una minuscola -e), giusto?
thebjorn,

probabilmente lo è. correggerà
JL Peyret l'

3

Il mio suggerimento è di aggiornare prima a Django==1.11.26, che è la versione più recente di Django che supporta sia Python 2 che Python 3. Rimani sulla tua attuale versione di Python 2.7 per ora.

Leggi attentamente le note di rilascio per 1.10.xe 1.11.x, controllando le deprecazioni e correggendo tutto ciò che ha smesso di funzionare dal tuo codice 1.9.x. Le cose si romperanno. Django si muove velocemente. Per un grande progetto Django, potrebbero essere necessarie molte modifiche al codice e se stai usando molti plugin o librerie di terze parti potresti dover destreggiarti tra loro. Alcune dipendenze di terze parti saranno probabilmente state completamente abbandonate, quindi è necessario trovare sostituzioni o rimuovere le funzionalità.

Per trovare le note di rilascio per ogni aggiornamento di versione, basta google "Novità di Django". Gli hit documenteranno meticolosamente tutti gli ammortamenti e le modifiche:

Una volta che la webapp sembra funzionare bene su Django 1.11, per tutti i test di passaggio (si fare avere una suite di test, giusto?) Allora si può fare la conversione Python 3, pur mantenendo la versione Django lo stesso. Django 1.11 supporta fino a Python 3.7, quindi sarebbe una buona versione come target. Aspettatevi unicode dappertutto, poiché le conversioni implicite tra byte e testo sono sparite ora e molte webapp di Python 2 si sono affidate a questo.

Una volta che il progetto sembra funzionare bene su Django 1.11 e Python 3.7, puoi pensare di aggiornare a Django 3.0, seguendo lo stesso processo di prima: leggere le note di rilascio, apportare le modifiche necessarie, eseguire la suite di test e verificare la webapp in un server di sviluppo manualmente.


1
Sicuramente la strada da percorrere. Ottieni il tuo codice di test per l'esecuzione su 2.7 e 3.x. Puoi avere 2 virtualenv diversi che puntano allo stesso repository git con pip install -E. Una volta che i test unitari sono in esecuzione, avvia l'utilizzo del test di Django-on-3x e continua a far funzionare il codice in 2 e 3. Con un po 'di codifica attenta e facendo attenzione a non bruciare i tuoi ponti 2.7 - nessuna stringa f per esempio - il passaggio sarà molto anticlimatica. Una volta che 3.x è completamente stabile, inizia a utilizzare solo il codice 3.x. Il vantaggio è che la produzione 2.7 è sempre al passo con il passaggio.
JL Peyret,

2

Prima aggiornerei a py3. Dovrai guardare setup.pynel repository Django sul ramo stable / 1.9.x ( https://github.com/django/django/blob/stable/1.9.x/setup.py ) per capire che il py3 le versioni supportate sono 3.4 (morte) e 3.5.

Una volta che sei su py3.5 e Django 1.9 puoi aggiornarne uno alla volta fino ad arrivare alla versione che vuoi terminare. Ad esempio Django 1.11 supporta py3.5 e py3.7, quindi

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

dj2.2 è la prima versione che supporta py3.8, ma probabilmente mi fermerei a py37 / dj2.2 se lavori in un ambiente normalmente conservativo.

Se hai altri pacchetti, dovrai trovare combinazioni di versioni che funzioneranno insieme in ogni passaggio. Avere un piano è la chiave e l'aggiornamento di un solo componente alla volta di solito ti farà risparmiare tempo.

La futura libreria ( https://python-future.org/ ) ti aiuterà in molte situazioni icky mentre hai bisogno di codice per essere eseguito su py27 e 3.x. anche sei è fantastico. Eviterei di far rotolare il tuo livello di compatibilità (perché reinventare la ruota?)

Se possibile, cerca di ottenere una copertura del test dell'unità fino al 75-85% prima di iniziare e imposta definitivamente il test automatico su entrambe le versioni "da" e "a" per ogni passaggio di aggiornamento. Assicurati di leggere e correggere tutti gli avvisi di Django prima di passare alla versione successiva: a Django interessa molto poco la compatibilità con le versioni precedenti, quindi di solito suggerirei di colpire tutte le versioni minori sul percorso di aggiornamento (o almeno assicurati di leggere "indietro incompatibilità "e elenchi di deprecazioni per ogni versione minore).

Buona fortuna (stiamo aggiornando una base di codice 300 + Kloc da py27 / dj1.7 in questo momento, quindi sento il tuo dolore ;-)


1
+1 sulla copertura del test. Questa è una metrica chiave qui, qualunque approccio uno finisca per prendere. Aiuta davvero quando si sperimentano cambiamenti pervasivi del codice e lo dico come qualcuno che non è affatto un appassionato di test TDD Red / Green. Scopri un modo per basare i tuoi risultati 2.7 e l'aggiornamento diventa molto più semplice.
JL Peyret,

2

Ho lo stesso tipo di problema con il mio progetto e ho provato Python 3.7.5 con Django versione 2.2.7.

Non dovresti andare con l'ultima versione di Python 3.8 o l'ultima versione di Django 3.0 perché potresti avere avuto la possibilità che per qualsiasi tipo di bug potresti non essere in grado di ottenere la soluzione corretta per le ultime versioni.


Questo dovrebbe essere un commento
Bruno

-2

Dovresti provare a sparare per le versioni attuali. Python 3.8 e Django 3.0. Le sei librerie aiuteranno con alcune modifiche alla convenzione. In entrambi i casi dovrai eseguire un refactoring in modo da poterlo rendere attuale.


3
Hai mai fatto un aggiornamento di Django? Questo è solo un pio desiderio. Andare direttamente su Python 3.8 e Django 3.0 da 2.7 / 1.9 sarà praticamente impossibile. Anche l'aggiornamento di versioni minori come Django da 1.9 a 1.10 può essere un processo difficile, con molte modifiche al codice necessarie.
wim

Sì, ho concesso che avevo il lusso e l'approvazione del tempo per fare un refactor completo e portare la domanda attuale. Ancora una volta le dimensioni dell'applicazione, la logica e i vincoli temporali sono un grosso problema per la maggior parte dei ragazzi, ma non hanno mai menzionato la dimensione dell'applicazione o il vincolo temporale, quindi ho raccomandato la mia opinione sulla "migliore soluzione" o "pio desiderio";)
Dave

Inoltre, se devi preoccuparti delle cose Ansible e anche in esecuzione su un Ubuntu LTS, troverai anche il supporto 3.7 su Ubuntu 18.04. I podcast sulla sicurezza che ascolto consigliano di lasciare che 3,8 si stabilizzi un po 'fino al rilascio di un punto o 2. -1 per rischi inutili.
JL Peyret,

Qualche buona raccomandazione sul podcast sulla sicurezza?
Dave,

Per Python sec, listennotes.com/podcasts/talk-python-to-me/… Ma penso che il diffidare di 3,8 per un po 'sia più recente. Risky Business è un podcast sulla sicurezza valido e divertente, soprattutto se si seguono le relazioni internazionali. Ci scusiamo per il voto negativo, ma sì, ciò che ha funzionato nel tuo caso potrebbe tarpare qualcun altro in un contesto diverso. Per la conversione da 2 a 3, consultare listennotes.com/podcasts/talk-python-to-me/…
JL Peyret,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.